{"id":4009,"date":"2022-01-07T13:58:00","date_gmt":"2022-01-07T12:58:00","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=4009"},"modified":"2022-01-05T16:12:39","modified_gmt":"2022-01-05T15:12:39","slug":"deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/","title":{"rendered":"Deep dive in Docker: Tips and Tricks to build Docker images optimized for security and size."},"content":{"rendered":"\n

A brief introduction<\/h2>\n\n\n\n

Nowadays we have a lot of workloads that are built on top of Docker and it is crucial to keep our Docker images secure and optimized for the cloud. We already covered Docker in our blog, you can dig further on the origins of Docker<\/a> or see a use case with WordPress<\/a>.<\/p>\n\n\n\n

In the next paragraphs, we will see a few tips on how we can avoid the most common security vulnerabilities and how to optimize the size of our Docker images.<\/p>\n\n\n\n

But first, we need to understand one of the core concepts of Docker: the layering system.<\/p>\n\n\n\n

The Dockerfile is the main file that defines how a Docker image is built. It defines the base image from which we start, the application\u2019s dependencies, how the application is packaged and how it is run.<\/p>\n\n\n\n

When we start the build process from a Dockerfile, the Docker engine creates a series of layers, one for each command in the Dockerfile. Every time we execute a command in the Dockerfile, a new layer containing the changes is created on top of the previous one. The Docker engine executes the commands sequentially and eventually combines all the layers to create the final image.<\/p>\n\n\n\n

How can I keep my Docker image small?<\/h2>\n\n\n\n

Start from a small base image. Alpine is a good choice<\/strong><\/h3>\n\n\n\n

Keeping the size small generally means that it is faster to build, deploy and run. To achieve that, a good idea is to start from a base image that is itself very small. You can use `alpine:3.15` which is just about 5.6 MB instead of `ubuntu:20.04` which is (at the time of this article) 72 MB.<\/p>\n\n\n\n

Alpine<\/a> is a general-purpose Linux distribution built around musl libc and <\/a>BusyBox that aims for simplicity, security, and resource efficiency. It contains only absolutely necessary packages because you know\u2026 if it\u2019s not included it can\u2019t break<\/em>.<\/p>\n\n\n\n

Keep in mind that it also has some drawbacks. For example, since Alpine is based on the musl C library, instead of the most widely used GNU C Library, you may encounter problems with some C-based dependencies.<\/p>\n\n\n\n

Use multi-stage Dockerfiles<\/strong><\/h3>\n\n\n\n

Aside from using Alpine as a base image, another method for reducing the size of your images is using multistage builds. A multistage build consists of a single Dockerfile in which we define multiple FROM instructions and each one defines a new stage.<\/p>\n\n\n\n

In each FROM we can start from a previous stage in order to take advantage of cached build artifacts or we can start from an entirely new base image and just copy some artifacts from the previous stage.<\/p>\n\n\n\n

Let\u2019s see a quick example:<\/p>\n\n\n\n

# Base image with dependencies\nFROM node:17.3.0-alpine3.12 AS base\nWORKDIR \/app\n# Copy package.json and package-lock.json\nCOPY package*.json .\/\n# Install dependencies\nRUN npm install\n \n \n# Build Stage\nFROM base AS build\nWORKDIR \/app\nCOPY . .\/\n# Build and bundle static files\nRUN npm run build\n \n \n# Release Stage\nFROM node:17.3.0-alpine3.12 AS release\nWORKDIR \/app\nCOPY --from=base \/app\/package.json .\/\n# Install app dependencies\nRUN npm install --only=production\nCOPY --from=build \/app\/dist\/ .\/\nCMD [ \"npm\", \"run\", \"start\" ]\n<\/code><\/pre>\n\n\n\n

In this multi-stage Dockerfile we created a base image that has all the required dependencies, we then created a builder stage, and finally, for the actual runtime image, we started from a clean image, installed the production requirements, and selectively copied only the required artifacts.<\/p>\n\n\n\n

By default, all stages are built but we can choose to build a specific stage with the flag `–target <stage-name>`<\/p>\n\n\n\n

`docker build –target release –tag image .`<\/p>\n\n\n\n

You can refer to the official docs<\/a> for further details. <\/p>\n\n\n\n

Make the most out of caching<\/strong><\/h3>\n\n\n\n

To fully take advantage of layer caching, write your Dockerfiles in a way that commands that will not change often are executed before others. That way the layers that are created first will be cached and reused. Although this will not change the final image size, it will make the builds faster. <\/p>\n\n\n\n

Use .dockerignore <\/strong><\/h3>\n\n\n\n

Add temporary files, intermediate build artifacts, local development files and sensitive info to .dockerignore exclude them. Next time you start a build it will be faster because the build context of the Docker engine will be smaller.<\/p>\n\n\n\n

Btw you should not commit sensitive info in your repository \ud83d\ude42<\/p>\n\n\n\n

Keep an eye on the layers \u2013 Dive<\/h2>\n\n\n\n

Dive<\/a> is a CLI tool that allows you to inspect the contents of each layer in a Docker Image. It can be very useful to see what has changed after each step in the dockerfile, because that way you can see if there are redundancies or unnecessary files in the image.<\/p>\n\n\n\n

To see it in action just run `dive <image-name>`<\/p>\n\n\n\n

<\/p>\n\n\n\n

\"Dive<\/figure><\/div>\n\n\n\n

<\/p>\n\n\n\n

The main features of Dive are:<\/p>\n\n\n\n

Show Docker image contents in each layer: <\/strong>It provides you a nice tree view of all the contents of the image in a specific layer of the image.<\/p>\n\n\n\n

Filter by new, modified, and removed files only:<\/strong> with the handy shortcuts you can enable\/disable the view of specific files.<\/p>\n\n\n\n

Estimate image efficiency:<\/strong> An experimental feature that shows you how much space is being wasted.<\/p>\n\n\n\n

Bonus tip for automation<\/strong><\/h2>\n\n\n\n

You can set the env variable `CI=true` to disable the interactive view and integrate it in a CI\/CD pipeline.<\/p>\n\n\n\n

You can create a .dive-ci file to customize three parameters for tests acceptance:<\/p>\n\n\n\n

`lowestEfficiency`, `highestWastedBytes` and `highestUserWastedPercent`.<\/p>\n\n\n\n

.dive-ci file:<\/p>\n\n\n\n

rules:\n # Lowest allowed efficiency percentage (value range between 0-1).\n lowestEfficiency: 0.95\n \n # If the amount of wasted space is at least X or larger than X, mark as failed.\n # Expressed in B, KB, MB, and GB.\n highestWastedBytes: 20MB\n \n # If the amount of wasted space makes up for X% or more of the image, mark as failed.\n # Note: the base image layer is NOT included in the total image size.\n # Expressed as a ratio between 0-1; fails if the threshold is met or crossed.\n highestUserWastedPercent: 0.10\n \n \n<\/code><\/pre>\n\n\n\n

<\/p>\n\n\n\n

\"Dive<\/figure><\/div>\n\n\n\n

<\/p>\n\n\n\n

Security basics<\/h2>\n\n\n\n

A basic rule of thumb is to start from the latest stable version<\/strong> of the base image. That way you will have the latest security patches for the native tools and libraries. The same rule also applies to the application-level dependencies.<\/p>\n\n\n\n

Another basic rule is to reduce the attack surface<\/strong>: you should have only the minimum set of tools and libraries required to run the application. To achieve this you can start from a very small base image (something like Alpine) and then install the application-level dependencies on top of that.<\/p>\n\n\n\n

One other good practice to follow is leveraging vulnerability scanning tools<\/strong> to check for known vulnerabilities in your Docker Images. Amazon\u2019s Elastic Container Registry allows us to scan our images at no additional cost!<\/p>\n\n\n\n

AWS ECR Scan<\/h2>\n\n\n\n

Amazon’s Elastic Container Registry (ECR) is a fully managed container registry that, among other features, offers a way to scan your images for vulnerabilities.<\/p>\n\n\n\n

Two scanning options are available<\/p>\n\n\n\n

Basic scanning<\/strong><\/h3>\n\n\n\n

Allows manual and automatic scanning of images and is a free service. It uses the Common Vulnerabilities and Exposures (CVEs) database from the open-source Clair project.<\/p>\n\n\n\n

Enhanced scanning<\/strong><\/h3>\n\n\n\n

Amazon ECR integrates with Amazon Inspector to provide automated scanning of the repositories. Your container images are continuously scanned and when new vulnerabilities appear Inspector notifies you through EventBridge.<\/p>\n\n\n\n

You can scan an image manually through the AWS Console or you can use the following AWS CLI command:<\/p>\n\n\n\n

aws ecr start-image-scan --repository-name nginx-test --image-id imageTag=base\n{\n\t\"registryId\": \"424242424242\",\n\t\"repositoryName\": \"nginx-test\",\n\t\"imageId\": {\n    \t\"imageDigest\": \"sha256:61191087790c31e43eb37caa10de1135b002f10c09fdda7fa8a5989db74033aa\",\n    \t\"imageTag\": \"base\"\n\t},\n\t\"imageScanStatus\": {\n    \t\"status\": \"IN_PROGRESS\"\n\t}\n}\n<\/code><\/pre>\n\n\n\n

and then use the following command to check the status of the scan:<\/p>\n\n\n\n

aws ecr describe-image-scan-findings --repository-name nginx-test --image-id imageTag=base\n{\n\t\"imageScanFindings\": {\n    \t\"findings\": [...],\n    \t\"imageScanCompletedAt\": \"2021-12-22T11:44:55+01:00\",\n    \t\"vulnerabilitySourceUpdatedAt\": \"2021-12-22T01:26:43+01:00\",\n    \t\"findingSeverityCounts\": {\n        \t\"HIGH\": 8,\n        \t\"MEDIUM\": 41,\n        \t\"LOW\": 23,\n        \t\"UNDEFINED\": 1,\n        \t\"INFORMATIONAL\": 67\n    \t}\n\t},\n\t\"registryId\": \"4242424242424242\",\n\t\"repositoryName\": \"nginx-test\",\n\t\"imageId\": {\n    \t\"imageDigest\": \"sha256:61191087790c31e43eb37caa10de1135b002f10c09fdda7fa8a5989db74033aa\",\n    \t\"imageTag\": \"base\"\n\t},\n\t\"imageScanStatus\": {\n    \t\"status\": \"COMPLETE\",\n    \t\"description\": \"The scan was completed successfully.\"\n\t}\n}\n<\/code><\/pre>\n\n\n\n

Scan on push<\/h2>\n\n\n\n

You can enable the ECR `ScanOnPush` feature on a specific repository or enable it on all your repositories by setting the Basic scanning configuration in the Console `Amazon ECR > Private registry > Scanning configuration`<\/p>\n\n\n\n

By setting this feature you can also benefit from the AWS EventBridge integration. Since every scan emits an event, you can intercept them with Event Bridge and build for example an event-driven notification system to alert you in case of critical security issues in your images.<\/p>\n\n\n\n

To Conclude<\/h2>\n\n\n\n

In this article, we covered some practices that you can adopt to optimize your Docker build process in multiple aspects.<\/p>\n\n\n\n

In regard to image size and build duration we saw some Dockerfile tips & tricks, we learned how to use Dive to inspect the layers and how to integrate it in a pipeline. And finally we saw how you can leverage ECR scan to automate scanning of your Images. <\/p>\n\n\n\n

If you’re still curious about the topic, here are some useful links:<\/p>\n\n\n\n

Alpine Linux<\/a><\/p>\n\n\n\n

AWS ECR<\/a><\/p>\n\n\n\n

Docker Multi Stage Build<\/a><\/p>\n\n\n\n

Clair Project<\/a><\/p>\n\n\n\n

Dive<\/a><\/p>\n\n\n\n

<\/p>\n\n\n\n

Contact us or write in comments to share your Docker experience! And see you in a few days for a new article on Proud2beCloud! <\/p>\n","protected":false},"excerpt":{"rendered":"

A brief introduction Nowadays we have a lot of workloads that are built on top of Docker and it is […]<\/p>\n","protected":false},"author":17,"featured_media":4034,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[478],"tags":[552,376,374],"yoast_head":"\nDeep dive in Docker: Tips and Tricks to build Docker images optimized for security and size. - Proud2beCloud Blog<\/title>\n<meta name=\"description\" content=\"In this article, we cover tips and best practices to follow to optimize Docker build process, always keeping an eye on security.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Optimizing Docker images for improved performance and security\" \/>\n<meta property=\"og:description\" content=\"How to avoid the most common security vulnerabilities and optimize the size of our Docker images.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/\" \/>\n<meta property=\"og:site_name\" content=\"Proud2beCloud Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-01-07T12:58:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-01-05T15:12:39+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2022\/01\/Copertina-blog-07-01-22_07-01-22-social-eng.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Mehmed Dourmouch\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Optimizing Docker images for improved performance and security\" \/>\n<meta name=\"twitter:description\" content=\"How to avoid the most common security vulnerabilities and optimize the size of our Docker images.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2022\/01\/Copertina-blog-07-01-22_07-01-22-social-eng.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mehmed Dourmouch\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/\",\"url\":\"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/\",\"name\":\"Deep dive in Docker: Tips and Tricks to build Docker images optimized for security and size. - Proud2beCloud Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.besharp.it\/#website\"},\"datePublished\":\"2022-01-07T12:58:00+00:00\",\"dateModified\":\"2022-01-05T15:12:39+00:00\",\"author\":{\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/78fb370d0b81a13b4d125ff596518191\"},\"description\":\"In this article, we cover tips and best practices to follow to optimize Docker build process, always keeping an eye on security.\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.besharp.it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Deep dive in Docker: Tips and Tricks to build Docker images optimized for security and size.\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.besharp.it\/#website\",\"url\":\"https:\/\/blog.besharp.it\/\",\"name\":\"Proud2beCloud Blog\",\"description\":\"il blog di beSharp\",\"alternateName\":\"Proud2beCloud Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.besharp.it\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/78fb370d0b81a13b4d125ff596518191\",\"name\":\"Mehmed Dourmouch\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c88fc04e52b5db309092da7fba855aee?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c88fc04e52b5db309092da7fba855aee?s=96&d=mm&r=g\",\"caption\":\"Mehmed Dourmouch\"},\"description\":\"DevOps Engineer. Very Dev, not so Ops. I like to break things and see what happens, I also automate everything. I often participate in cybersecurity CTFs and in my free time I produce cacophony with my guitar.\",\"url\":\"https:\/\/blog.besharp.it\/author\/mehmed-dourmouch\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Deep dive in Docker: Tips and Tricks to build Docker images optimized for security and size. - Proud2beCloud Blog","description":"In this article, we cover tips and best practices to follow to optimize Docker build process, always keeping an eye on security.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/","og_locale":"en_US","og_type":"article","og_title":"Optimizing Docker images for improved performance and security","og_description":"How to avoid the most common security vulnerabilities and optimize the size of our Docker images.","og_url":"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/","og_site_name":"Proud2beCloud Blog","article_published_time":"2022-01-07T12:58:00+00:00","article_modified_time":"2022-01-05T15:12:39+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2022\/01\/Copertina-blog-07-01-22_07-01-22-social-eng.png","type":"image\/png"}],"author":"Mehmed Dourmouch","twitter_card":"summary_large_image","twitter_title":"Optimizing Docker images for improved performance and security","twitter_description":"How to avoid the most common security vulnerabilities and optimize the size of our Docker images.","twitter_image":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2022\/01\/Copertina-blog-07-01-22_07-01-22-social-eng.png","twitter_misc":{"Written by":"Mehmed Dourmouch","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/","url":"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/","name":"Deep dive in Docker: Tips and Tricks to build Docker images optimized for security and size. - Proud2beCloud Blog","isPartOf":{"@id":"https:\/\/blog.besharp.it\/#website"},"datePublished":"2022-01-07T12:58:00+00:00","dateModified":"2022-01-05T15:12:39+00:00","author":{"@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/78fb370d0b81a13b4d125ff596518191"},"description":"In this article, we cover tips and best practices to follow to optimize Docker build process, always keeping an eye on security.","breadcrumb":{"@id":"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.besharp.it\/deep-dive-in-docker-tips-and-tricks-to-build-docker-images-optimized-for-security-and-size\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.besharp.it\/"},{"@type":"ListItem","position":2,"name":"Deep dive in Docker: Tips and Tricks to build Docker images optimized for security and size."}]},{"@type":"WebSite","@id":"https:\/\/blog.besharp.it\/#website","url":"https:\/\/blog.besharp.it\/","name":"Proud2beCloud Blog","description":"il blog di beSharp","alternateName":"Proud2beCloud Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.besharp.it\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/78fb370d0b81a13b4d125ff596518191","name":"Mehmed Dourmouch","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/c88fc04e52b5db309092da7fba855aee?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c88fc04e52b5db309092da7fba855aee?s=96&d=mm&r=g","caption":"Mehmed Dourmouch"},"description":"DevOps Engineer. Very Dev, not so Ops. I like to break things and see what happens, I also automate everything. I often participate in cybersecurity CTFs and in my free time I produce cacophony with my guitar.","url":"https:\/\/blog.besharp.it\/author\/mehmed-dourmouch\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts\/4009"}],"collection":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/comments?post=4009"}],"version-history":[{"count":0,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts\/4009\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/media\/4034"}],"wp:attachment":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/media?parent=4009"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/categories?post=4009"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/tags?post=4009"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}