{"id":27000,"date":"2022-10-03T14:03:38","date_gmt":"2022-10-03T14:03:38","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=27000"},"modified":"2025-07-12T05:41:39","modified_gmt":"2025-07-12T05:41:39","slug":"tutorial-on-docker-architecture-its-components-and-how-it-works","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/tutorial-on-docker-architecture-its-components-and-how-it-works\/","title":{"rendered":"Docker Tutorials: Docker Architecture and How it works?"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"654\" height=\"688\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-1.jpg\" alt=\"\" class=\"wp-image-32680\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-1.jpg 654w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-1-285x300.jpg 285w\" sizes=\"auto, (max-width: 654px) 100vw, 654px\" \/><\/figure>\n\n\n\n<p>Docker architecture consists of several components that work together to provide a platform for building, shipping, and running containers. These components include:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Docker Engine: This is the core component of Docker, and it is responsible for building and running containers. The Docker Engine provides a REST API for interacting with containers, as well as a command-line interface for managing containers.<\/li>\n\n\n\n<li>Docker Images: Docker images are snapshots of a container that can be used to launch new containers. Images are stored in a registry, such as Docker Hub or a private registry, and can be pulled down to a local machine for use.<\/li>\n\n\n\n<li>Docker Registries: Docker registries are where Docker images are stored and distributed. Docker Hub is a public registry that is free to use, but organizations can also set up their own private registries to store and distribute images.<\/li>\n\n\n\n<li>Docker Containers: Docker containers are isolated environments that run applications. Containers are built from images and can be launched on any host that has the Docker Engine installed.<\/li>\n\n\n\n<li>Docker Compose: Docker Compose is a tool for defining and running multi-container applications using a YAML file. It allows developers to define the services that make up an application, as well as the relationships between those services, and then start and stop the entire application with a single command.<\/li>\n\n\n\n<li>Docker Swarm: Docker Swarm is a native clustering solution for Docker that provides high-availability and scalability for containers. Swarm allows administrators to manage a swarm of Docker nodes as a single virtual host, making it easier to deploy and manage containers at scale.<\/li>\n<\/ol>\n\n\n\n<p>In summary, Docker architecture consists of several components, including the Docker Engine, Docker Images, Docker Registries, Docker Containers, Docker Compose, and Docker Swarm. These components work together to provide a platform for building, shipping, and running containers.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"650\" height=\"599\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-2.png\" alt=\"\" class=\"wp-image-32682\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-2.png 650w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-2-300x276.png 300w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What is Docker Workflow?<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"450\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-3.jpg\" alt=\"\" class=\"wp-image-32684\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-3.jpg 800w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-3-300x169.jpg 300w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-3-768x432.jpg 768w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2023\/02\/docker-architecture-3-355x199.jpg 355w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p>The Docker workflow involves several steps to build, package, and run applications as containers. The basic steps are as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Writing Dockerfiles: A Dockerfile is a script that contains instructions for building a Docker image. It specifies the base image to use, the application code to include, and the environment variables to set.<\/li>\n\n\n\n<li>Building Docker Images: Docker images are built from Dockerfiles using the &#8220;docker build&#8221; command. The build process follows the instructions in the Dockerfile to create a new image that includes the application code and its dependencies.<\/li>\n\n\n\n<li>Storing Docker Images: Docker images can be stored in a Docker registry, such as Docker Hub or a private registry. Docker images are stored as layers, making it possible to share images between different projects and build new images from existing images.<\/li>\n\n\n\n<li>Running Docker Containers: Docker containers are launched from Docker images using the &#8220;docker run&#8221; command. Containers are isolated environments that run applications, and they can be launched on any host that has the Docker Engine installed.<\/li>\n\n\n\n<li>Managing Docker Containers: Docker provides several tools for managing containers, including the &#8220;docker ps&#8221; command to list running containers, the &#8220;docker stop&#8221; command to stop containers, and the &#8220;docker rm&#8221; command to remove containers.<\/li>\n\n\n\n<li>Deploying Docker Containers: Docker containers can be deployed to a variety of environments, including physical servers, virtual machines, cloud platforms, and more. Docker Compose and Docker Swarm are two tools that can be used to deploy and manage containers at scale.<\/li>\n<\/ol>\n\n\n\n<p>In summary, the Docker workflow involves several steps, including writing Dockerfiles, building Docker images, storing Docker images, running Docker containers, managing Docker containers, and deploying Docker containers. The Docker platform provides a set of tools for building, packaging, and running applications as containers, making it easier to deploy and manage applications at scale.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"docker-cli-docker\">Docker CLI (docker)<\/h2>\n\n\n\n<p><code>\/usr\/bin\/docker<\/code><\/p>\n\n\n\n<p>Docker is used as a reference to the whole set of docker tools and at the beginning, it was a monolith. But now&nbsp;<code>docker-cli<\/code>&nbsp;is only responsible for user-friendly communication with docker.<\/p>\n\n\n\n<p>So the command\u2019s like&nbsp;<code>docker build ...<\/code>&nbsp;<code>docker run ...<\/code>&nbsp;are handled by Docker CLI and result in the invocation of&nbsp;<strong>dockerd<\/strong>&nbsp;API.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"dockerd\">Dockerd<\/h2>\n\n\n\n<p><code>\/usr\/bin\/dockerd<\/code><\/p>\n\n\n\n<p>The Docker daemon &#8211;&nbsp;<strong>dockerd<\/strong>&nbsp;listens for Docker API requests and manages the host\u2019s Container life-cycles by utilizing&nbsp;<strong>contanerd<\/strong><\/p>\n\n\n\n<p><code>dockerd<\/code>&nbsp;can listen for Docker Engine API requests via three different types of Socket: unix, tcp, and fd. By default, a unix domain socket is created at&nbsp;<code>\/var\/run\/docker.sock<\/code>, requiring either root permission, or docker group membership. On&nbsp;<a href=\"https:\/\/alexander.holbreich.org\/tag\/systemd\/\" target=\"_blank\" rel=\"noopener\">Systemd<\/a>&nbsp;based systems, you can communicate with the daemon via Systemd socket activation, use&nbsp;<code>dockerd -H fd:\/\/<\/code>.<\/p>\n\n\n\n<p>There are many&nbsp;<a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/dockerd\/\" target=\"_blank\" rel=\"noopener\">configuration options<\/a>&nbsp;for the daemon, which are worth checking if you work with docker (dockerd).<\/p>\n\n\n\n<p>My impression is that&nbsp;<code>dockerd<\/code>&nbsp;is here to serve all the features of Docker (or Docker EE) platform, while actual container life-cycle management is \u201coutsourced\u201d to&nbsp;<strong>containerd<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"containerd\">Containerd<\/h2>\n\n\n\n<p><code>\/usr\/bin\/docker-containerd<\/code><\/p>\n\n\n\n<p><code>containerd<\/code>&nbsp;was introduced in Docker 1.11 and since then took the main responsibility of managing containers life-cycle.&nbsp;<code>containerd<\/code>&nbsp;is the&nbsp;<em>executor for containers<\/em>, but has a wider scope than&nbsp;<em>just executing<\/em>&nbsp;containers. So it also takes care of:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Image push and pull<\/li>\n\n\n\n<li>Managing storage<\/li>\n\n\n\n<li>Of course executing of Containers by calling&nbsp;<strong>runc<\/strong>&nbsp;with the right parameters to run containers\u2026<\/li>\n\n\n\n<li>Managing of network primitives for interfaces<\/li>\n\n\n\n<li>Management of network namespaces containers to join existing namespaces<\/li>\n<\/ul>\n\n\n\n<p><em><code>containerd<\/code>&nbsp;fully leverages the&nbsp;OCI runtime specification<sup><a href=\"https:\/\/alexander.holbreich.org\/docker-components-explained\/#fn:1\" target=\"_blank\" rel=\"noopener\">1<\/a><\/sup>, image format specifications, and OCI reference implementation (runc)<\/em>. Because of its massive adoption, containerd is the industry standard for implementing OCI. It is currently available for Linux and Windows.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/github.com\/containerd\/containerd\/raw\/master\/design\/architecture.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>As shown in the picture above,&nbsp;<code>contained<\/code>&nbsp;includes a daemon exposing gRPC API over a local UNIX socket. The API is a low-level one designed for higher layers to wrap and extend.&nbsp;<code>Containerd<\/code>&nbsp;uses&nbsp;<code>RunC<\/code>&nbsp;to run containers according to the OCI specification.<\/p>\n\n\n\n<p><code>containerd<\/code>&nbsp;is based on the Docker Engine\u2019s core container runtime to benefit from its maturity and existing contributors, however,&nbsp;<code>containerd<\/code>&nbsp;is designed to be embedded into a larger system, rather than being used directly by developers or end-users.<\/p>\n\n\n\n<p>Well, now other vendors can use containers without having to deal with docker-related parts.<\/p>\n\n\n\n<p>let\u2019s go through some subsystems of&nbsp;<code>containerd<\/code>\u2026<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"runc\">RunC<\/h3>\n\n\n\n<p><code>\/usr\/bin\/docker-runc<\/code>&nbsp;runc (OCI runtime) canbe seen as component of containerd.<\/p>\n\n\n\n<p><code>runc<\/code>&nbsp;is a command-line client for running applications packaged according to the OCI format and is a compliant implementation of the OCI spec.<\/p>\n\n\n\n<p>Containers are configured using bundles. A bundle for a container is a directory that includes a specification file named \u201cconfig.json\u201d and a root filesystem. The root filesystem contains the contents of the container.<\/p>\n\n\n\n<p>Assuming you have an OCI bundle you can execute the container<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># run as root<\/span>\ncd \/mycontainer\nrunc run mycontainerid\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id=\"containerd-ctr\">containerd-ctr<\/h3>\n\n\n\n<p><code>\/usr\/bin\/docker-containerd-ctr<\/code>&nbsp;(docker-)containerd-ctr &#8211; it\u2019s barebone CLI (ctr) designed specifically for development and debugging purposes for direct communication with&nbsp;<code>containerd<\/code>. It\u2019s included in the releases of&nbsp;<code>containerd<\/code>. By that less interesting for docker users.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"containerd-shim\">containerd-shim<\/h3>\n\n\n\n<p><code>\/usr\/bin\/docker-containerd-shim<\/code><\/p>\n\n\n\n<p><em>The shim allows for daemon-less containers<\/em>.&nbsp;<a href=\"https:\/\/groups.google.com\/forum\/#!topic\/docker-dev\/zaZFlvIx1_k\" target=\"_blank\" rel=\"noopener\">According to Michael Crosby<\/a>&nbsp;it basically sits as the parent of the container\u2019s process to facilitate a few things.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First it allows the runtimes, i.e.&nbsp;<code>runc<\/code>, to exit after it starts the container. This way we don\u2019t have to have the long-running runtime processes for containers.<\/li>\n\n\n\n<li>Second it keeps the STDIO and other fds open for the container in the case&nbsp;<code>containerd<\/code>&nbsp;and\/or docker both die. If the shim was not running then the parent site of the pipes or the TTY master would be closed and the container would exit.<\/li>\n\n\n\n<li>Finally it allows the container\u2019s exit status to be reported back to a higher level tool like docker without having the be the actual parent of the container\u2019s process and do a wait4.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-it-all-works-together\">How it all works together<\/h2>\n\n\n\n<p>We can do an experiment. First we check what&nbsp;<em>Docker processes<\/em>&nbsp;are running right after Docker installation.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">ps fxa | grep docker -A <span class=\"hljs-number\">3<\/span>\n<span class=\"hljs-comment\"># prints:<\/span>\n<span class=\"hljs-number\">2239<\/span> ?        Ssl    <span class=\"hljs-number\">0<\/span>:<span class=\"hljs-number\">27<\/span> \/usr\/bin\/dockerd -H fd:<span class=\"hljs-comment\">\/\/<\/span>\n <span class=\"hljs-number\">2397<\/span> ?        Ssl    <span class=\"hljs-number\">0<\/span>:<span class=\"hljs-number\">18<\/span>  \\_ docker-containerd -l unix:<span class=\"hljs-comment\">\/\/\/var\/run\/docker\/libcontainerd\/docker-containerd.sock ...<\/span>\n...\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>well at this point we see that dockerd is started and containerd is running as a child process too. Like described,&nbsp;<code>dockerd<\/code>&nbsp;needs&nbsp;<code>containerd<\/code>&nbsp;\ud83d\ude09 Now let\u2019s run one simple container, that executes for a minute and then exits.<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">docker run -d alpine sleep 60\n<\/code><\/span><\/pre>\n\n\n<p>Now we should see it in the process list in the next 60 seconds. Let\u2019s check again:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">ps fxa | grep dockerd -A <span class=\"hljs-number\">3<\/span>\n<span class=\"hljs-comment\">#prints<\/span>\n <span class=\"hljs-number\">2239<\/span> ?        Ssl    <span class=\"hljs-number\">0<\/span>:<span class=\"hljs-number\">28<\/span> \/usr\/bin\/dockerd -H fd:<span class=\"hljs-comment\">\/\/<\/span>\n <span class=\"hljs-number\">2397<\/span> ?        Ssl    <span class=\"hljs-number\">0<\/span>:<span class=\"hljs-number\">19<\/span>  \\_ docker-containerd -l unix:<span class=\"hljs-comment\">\/\/\/var\/run\/docker\/libcontainerd\/docker-containerd.sock ...<\/span>\n<span class=\"hljs-number\">15476<\/span> ?        Sl     <span class=\"hljs-number\">0<\/span>:<span class=\"hljs-number\">00<\/span>      \\_ docker-containerd-shim <span class=\"hljs-number\">3<\/span>da7... \/<span class=\"hljs-keyword\">var<\/span>\/run\/docker\/libcontainerd\/<span class=\"hljs-number\">3<\/span>da7.. docker-runc\n<span class=\"hljs-number\">15494<\/span> ?        Ss     <span class=\"hljs-number\">0<\/span>:<span class=\"hljs-number\">00<\/span>          \\_ sleep <span class=\"hljs-number\">60<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now we see the whole process chain:<\/p>\n\n\n\n<p><strong>dockerd<\/strong>&nbsp;\u2013&gt;&nbsp;<strong>containerd<\/strong>&nbsp;\u2013&gt;&nbsp;<strong>containerd-shim<\/strong>&nbsp;\u2013&gt; \u201csleep 60\u201d (desired process in the container).<\/p>\n\n\n\n<p>We do not see&nbsp;<code>runc<\/code>&nbsp;in the chain, we know&nbsp;<code>containerd-shim<\/code>&nbsp;takes over after&nbsp;<code>runc<\/code>&nbsp;has started the container. Also, we know that theoretically&nbsp;<code>containerd-shim<\/code>&nbsp;can survive the crash of&nbsp;<code>containerd<\/code>. But in the current docker version, it\u2019s&nbsp;<a href=\"https:\/\/docs.docker.com\/config\/containers\/live-restore\/#enable-live-restore\" target=\"_blank\" rel=\"noopener\">not activated by default<\/a>.<\/p>\n\n\n\n<p>However, it\u2019s a pretty long chain with possible disadvantages that such chains might have.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"how-it-all-works-in-kubernetes\">How it all works in Kubernetes<\/h3>\n\n\n\n<p>You might imagine that&nbsp;<a href=\"https:\/\/alexander.holbreich.org\/tag\/k8n\/\" target=\"_blank\" rel=\"noopener\">Kubernetes<\/a>&nbsp;do not need Docker-specific parts. As of now, it\u2019s exactly the case\u2026<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/github.com\/containerd\/cri\/raw\/master\/docs\/cri.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>Kubernetes \u201cspeaks\u201d with&nbsp;<code>contanerd<\/code>&nbsp;directly as depicted in the picture. If interested, check&nbsp;<a href=\"https:\/\/kubernetes.io\/blog\/2017\/11\/containerd-container-runtime-options-kubernetes\" target=\"_blank\" rel=\"noopener\">how it was in between<\/a>.<\/p>\n\n\n\n<p>I hope this might help all Docker users. Give me a hint if something is not precise.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The&nbsp;<a href=\"https:\/\/github.com\/opencontainers\/runtime-spec\" target=\"_blank\" rel=\"noopener\">OCI Runtime Specification<\/a>&nbsp;outlines how to run a containers \u201cfilesystem bundle\u201d that is unpacked on disk. At a high level, an OCI implementation would download an OCI Image (<a href=\"https:\/\/github.com\/opencontainers\/image-spec\" target=\"_blank\" rel=\"noopener\">OCI Image Specification<\/a>) then unpack that image into an OCI Runtime filesystem bundle. At this point, the OCI Runtime Bundle would be run by an OCI Runtime.&nbsp;<a href=\"https:\/\/alexander.holbreich.org\/docker-components-explained\/#fnref:1\" target=\"_blank\" rel=\"noopener\">\u21a9\ufe0e<\/a><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"reference\">Reference<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>https:\/\/alexander.holbreich.org\/docker-components-explained\/<\/li>\n\n\n\n<li><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Docker architecture consists of several components that work together to provide a platform for building, shipping, and running containers. These components include: In summary, Docker architecture consists of several components, including the Docker Engine, Docker Images, Docker Registries, Docker Containers, Docker Compose, and Docker Swarm. These components work together to provide a platform for building,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","_joinchat":[],"footnotes":""},"categories":[4862],"tags":[],"class_list":["post-27000","post","type-post","status-publish","format-standard","hentry","category-docker"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/27000","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=27000"}],"version-history":[{"count":5,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/27000\/revisions"}],"predecessor-version":[{"id":32685,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/27000\/revisions\/32685"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=27000"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=27000"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=27000"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}