<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://www.rpatterson.net/</id>
  <title>Ross Patterson's Blog - Posts tagged DinD</title>
  <updated>2025-07-14T00:00:48.528816+00:00</updated>
  <link href="https://www.rpatterson.net/"/>
  <link href="https://www.rpatterson.net/blog/tag/dind/atom.xml" rel="self"/>
  <generator uri="https://ablog.readthedocs.io/" version="0.11.12">ABlog</generator>
  <entry>
    <id>https://www.rpatterson.net/blog/dind-reproduce-deploys/</id>
    <title>Reproducing Deployments with Docker-in-Docker</title>
    <updated>2021-04-09T00:00:00+00:00</updated>
    <author>
      <name>Ross Patterson</name>
    </author>
    <content type="html">&lt;section id="reproducing-deployments-with-docker-in-docker"&gt;

&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Debugging deployment issues locally by falling down the &lt;a class="reference external" href="https://hub.docker.com/_/docker"&gt;Docker-in-Docker&lt;/a&gt; (DinD)
rabbit hole.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;TL;DR:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;You can run a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;#&lt;/span&gt; &lt;span class="pre"&gt;dockerd&lt;/span&gt;&lt;/code&gt; daemon inside a &lt;a class="reference external" href="https://docs.docker.com/"&gt;Docker&lt;/a&gt; container which can be used with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$&lt;/span&gt; &lt;span class="pre"&gt;docker-compose&lt;/span&gt; &lt;span class="pre"&gt;...&lt;/span&gt;&lt;/code&gt; to (almost) completely reproduce hosted deployment
environments on one’s development laptop.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;As noted in &lt;a class="reference external" href="../docker-gotchas/"&gt;a recent post&lt;/a&gt;, I seem to have become the &lt;a class="reference external" href="https://docs.docker.com/"&gt;Docker&lt;/a&gt; wrangler on the team
for my recent projects.  Also recently, I’m getting the distinct impression that
containerization has or is beginning to reach that special point in the life-cycle of a
technology where it is sufficiently widely adopted to be misused and has been in use
long enough for that misuse to hurt.  This is one of those ironic signs of success and
utility but knowing that doesn’t lessen the pain or cost of the individual case one may
run into.&lt;/p&gt;
&lt;p&gt;Most recently, I was dealing with problematically fragile container-based deployments
where the team was getting bitten over and over again by deployment details that weren’t
causing problems in our local container-based development environments but were causing
problems when CD pushed our changes to real hosted deployments.  Specifically, the
hosted deployments were failing on such things as filesystem paths and IP addresses.  To
make things worse, the internal CI/CD pipeline was under-resourced and very slow making
the inner loop of testing changes painfully slow and wasteful.&lt;/p&gt;
&lt;p&gt;Before you think it, this is a project where there are many things that need to be
re-worked to be in alignment with current best practices and thus less fragile: from how
containers are used, to keeping CI/CD responsive, to how deployment is orchestrated.
Deployments should &lt;em&gt;not&lt;/em&gt; be sensitive to changes in filesystem paths and IP addresses,
to be sure.  The project was a &lt;a class="reference external" href="https://docs.python.org/3/howto/pyporting.html"&gt;Python 3 upgrade&lt;/a&gt;, however, and we’d done just about
all there was appetite for in terms of cleanup work that wasn’t directly related to the
upgrade.  As software developers, it’s our job to figure out how to solve difficult
technical problems, including the difficulty of getting sub-optimal technology usage to
work.&lt;/p&gt;
&lt;p&gt;At any rate, the tax we were paying for this deployment sensitivity was so high and was
happening often enough that I decided it was past time to work on a way to try and
reproduce the real hosted deployment environment more completely, preferably locally.
Reproducing deployment hosts as thoroughly as possible without turning my development
laptop in to the deployment hosts feels like an isolation issue, so I reached for
containers and Docker.  Specifically, I wanted to start with a container image as close
to the VM image used by the deployment hosts as possible and figure out how to run the
actual application container images within those “host containers”.  IOW, can I run
Docker containers within a Docker container?  Yup, &lt;a class="reference external" href="https://www.docker.com/blog/docker-can-now-run-within-docker/"&gt;for some time now&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It turns out that Docker now provides an &lt;a class="reference external" href="https://hub.docker.com/_/docker"&gt;official Docker-in-Docker (DinD) image&lt;/a&gt;.
After reading it’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;./Dockerfile&lt;/span&gt;&lt;/code&gt; and some blog posts detailing how to run DinD, I
decided it would be more efficient and maintainable to use the official &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;docker:dind&lt;/span&gt;&lt;/code&gt;
image as my base image and extend it to match the project’s deployment hosts rather than
the other way around, start with a base image close to the deployment hosts and get DinD
working in those.  A quick &lt;a class="reference download internal" download="" href="../../../_downloads/3a417606cbc7bb8ed3e711209c9136b3/Dockerfile"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;./Dockerfile&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; reproduced the
deployment host content in an image, including deployment host filesystem paths and
users, e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/home/ec2-user/&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-dockerfile notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;docker:dind&lt;/span&gt;
&lt;span class="c"&gt;# Defensive shell settings, avoid silent failures&lt;/span&gt;
&lt;span class="k"&gt;SHELL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/bin/ash&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-xeu&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;# Install required OS host packages&lt;/span&gt;
&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;apk&lt;span class="w"&gt; &lt;/span&gt;--no-cache&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;py-pip&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;python3-dev&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;libffi-dev&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;openssl-dev&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gcc&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;libc-dev&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;rust&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cargo&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;make&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;pip3&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;docker-compose&amp;#39;&lt;/span&gt;

&lt;span class="c"&gt;# Duplicate the AWS EC2 user&lt;/span&gt;
&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;adduser&lt;span class="w"&gt; &lt;/span&gt;--disabled-password&lt;span class="w"&gt; &lt;/span&gt;--gecos&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;EC2 User,,,&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ec2-user
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A &lt;a class="reference download internal" download="" href="../../../_downloads/39f6a6af29cc8b4aa915a8f169b656cf/docker-compose.yml"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;./docker-compose.yml&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; file reproduces the running
deployment hosts including network topology such as subnet and host IP addresses.  I
also abuse the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;./docker-compose.yml&lt;/span&gt;&lt;/code&gt; file to build &lt;a class="reference download internal" download="" href="../../../_downloads/054317702b0a3c1298bd02befac454ef/Dockerfile"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;the&lt;/span&gt; &lt;span class="pre"&gt;application&lt;/span&gt; &lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ipam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Match the hosted deployment network&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.81.82.0/24&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="c1"&gt;# Build custom container image, to be loaded into the nested host Docker daemons.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;foo-app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./foo-app/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar-company/foo-app:dev&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Build only, don&amp;#39;t actually run as a service&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Emulate deployment hosts running Docker daemons&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;foo-host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar-company/foo-host:dev&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Just build the image, don&amp;#39;t actually run as a service&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;foo-host-corge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar-company/foo-host:dev&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo-host&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Match the hosted deployment IP&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;ipv4_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.81.82.100&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Docker-in-Docker requires data on a real filesystem&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./var/lib/foo-host-corge/docker/:/var/lib/docker/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Reproduce where project data is stored in hosted deployments&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./var/lib/foo-data/:/home/ec2-user/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Make source editable&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./foo-app/:/srv/foo-app/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Reproduce deployment containers using a `$ docker-compose ...` configuration&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# specific to the deployment host&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./foo-host-corge/:/srv/foo-host-corge/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;working_dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/srv/foo-host-corge/&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;foo-host-grault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar-company/foo-host:dev&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo-host&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Match the hosted deployment IP&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;ipv4_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.81.82.101&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Docker-in-Docker requires data on a real filesystem&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./var/lib/foo-host-grault/docker/:/var/lib/docker/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Reproduce where project data is stored in hosted deployments&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./var/lib/foo-data/:/home/ec2-user/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Make source editable&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./foo-app/:/srv/foo-app/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Reproduce deployment containers using a `$ docker-compose ...` configuration&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# specific to the deployment host&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./foo-host-grault/:/srv/foo-host-grault/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;working_dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/srv/foo-host-grault/&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Nested &lt;a class="reference download internal" download="" href="../../../_downloads/abbd0e228e5961c04e64b6912ef76c57/docker-compose.yml"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;./foo-host-corge/docker-compose.yml&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; and
&lt;a class="reference download internal" download="" href="../../../_downloads/7c8cd03aca75b1de1f3233766103c84b/docker-compose.yml"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;./foo-host-grault/docker-compose.yml&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;
files reproduce how the application containers are run on the real deployment hosts, but
run instead within the nested DinD containers that reproduce the deployment hosts:&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;postgres&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5432:5432&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./.env&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;foo-app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar-company/foo-app:dev&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;extra_hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;redis:10.81.82.101&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Make source editable&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/srv/foo-app/:/srv/foo-app/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Reproduce where project data is stored in hosted deployments&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/home/ec2-user/foo-data/:/srv/foo-data/&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;redis&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;6379:6379&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;foo-app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar-company/foo-app:dev&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;extra_hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;postgres:10.81.82.100&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Make source editable&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/srv/foo-app/:/srv/foo-app/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Reproduce where project data is stored in hosted deployments&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/home/ec2-user/foo-data/:/srv/foo-data/&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Use some &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$&lt;/span&gt; &lt;span class="pre"&gt;docker&lt;/span&gt; &lt;span class="pre"&gt;...&lt;/span&gt;&lt;/code&gt; commands and some shell to push the application images into
the nested &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;#&lt;/span&gt; &lt;span class="pre"&gt;dockerd&lt;/span&gt;&lt;/code&gt; daemons and some &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$&lt;/span&gt; &lt;span class="pre"&gt;docker-compose&lt;/span&gt; &lt;span class="pre"&gt;...&lt;/span&gt;&lt;/code&gt; commands to run
containers using those images, along with the rest of the deployment configuration.  I
use a &lt;a class="reference download internal" download="" href="../../../_downloads/64071479609507d0a270e2eba4423b83/Makefile"&gt;&lt;code class="xref download docutils literal notranslate"&gt;&lt;span class="pre"&gt;./Makefile&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; to stitch this all together but use what you
like:&lt;/p&gt;
&lt;div class="highlight-makefile notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c"&gt;# Reproduce hosted deployments in nested Docker (DinD)&lt;/span&gt;

&lt;span class="c"&gt;### Defensive settings for make:&lt;/span&gt;
&lt;span class="c"&gt;#     https://tech.davis-hansson.com/p/make/&lt;/span&gt;
&lt;span class="nv"&gt;SHELL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash
&lt;span class="nf"&gt;.ONESHELL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;.SHELLFLAGS&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;-xeu&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;pipefail&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;inherit_errexit&lt;span class="w"&gt; &lt;/span&gt;-c
&lt;span class="nf"&gt;.SILENT&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="nf"&gt;.DELETE_ON_ERROR&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="nv"&gt;MAKEFLAGS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--warn-undefined-variables
&lt;span class="nv"&gt;MAKEFLAGS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--no-builtin-rules


&lt;span class="c"&gt;# Top-level targets&lt;/span&gt;

&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;log&lt;/span&gt;/&lt;span class="n"&gt;docker&lt;/span&gt;-&lt;span class="n"&gt;compose&lt;/span&gt;-&lt;span class="n"&gt;build&lt;/span&gt;.&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;-&lt;span class="n"&gt;host&lt;/span&gt;-&lt;span class="n"&gt;corge&lt;/span&gt;/.&lt;span class="n"&gt;env&lt;/span&gt;

&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-T&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo-host-corge&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-T&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo-host-grault&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;span class="w"&gt;	&lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-T&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo-host-corge&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-T&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo-host-grault&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;ps

&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;
&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;
&lt;span class="c"&gt;# Demonstrate that deployment host network topology and hostnames are reproduced&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-corge&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;nc&lt;span class="w"&gt; &lt;/span&gt;-vz&lt;span class="w"&gt; &lt;/span&gt;redis&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6379&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-grault&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;nc&lt;span class="w"&gt; &lt;/span&gt;-vz&lt;span class="w"&gt; &lt;/span&gt;postgres&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5432&lt;/span&gt;
&lt;span class="c"&gt;# Demonstrate that deployment host filesystem paths and data are reproduced&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-rfv&lt;span class="w"&gt; &lt;/span&gt;./var/lib/foo-data/*
&lt;span class="w"&gt;	&lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/lib/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-corge&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/ec2-user/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-grault&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/ec2-user/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-corge&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/srv/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-grault&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/srv/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-grault&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/srv/foo-data/bar.txt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/lib/foo-data/bar.txt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-corge&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/srv/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-grault&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-al&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/srv/foo-data/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-grault&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-app&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/srv/foo-data/bar.txt&amp;quot;&lt;/span&gt;

&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;
&lt;span class="nf"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;down&lt;span class="w"&gt; &lt;/span&gt;--rmi&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-v
&lt;span class="w"&gt;	&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-rf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/lib/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-pv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/log/backups/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/log/docker-compose-build.log&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;--backup&lt;span class="o"&gt;=&lt;/span&gt;numbered&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/log/docker-compose-build.log&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	        &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/log/backups/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./foo-host-corge/.env&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;--backup&lt;span class="o"&gt;=&lt;/span&gt;numbered&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./foo-host-corge/.env&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;	        &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./var/log/backups/&amp;quot;&lt;/span&gt;

&lt;span class="c"&gt;# Real targets&lt;/span&gt;

&lt;span class="nf"&gt;var/log/docker-compose-build.log&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;-&lt;span class="n"&gt;app&lt;/span&gt;/&lt;span class="n"&gt;Dockerfile&lt;/span&gt; &lt;span class="n"&gt;Dockerfile&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;-&lt;span class="n"&gt;compose&lt;/span&gt;.&lt;span class="n"&gt;yml&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-pv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dir&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;@&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;--pull&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;@&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="c"&gt;# Wait for the nested deployment host `# dorckerd` daemons to become available&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo-host-corge&lt;span class="w"&gt; &lt;/span&gt;foo-host-grault
&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;timeout&lt;span class="w"&gt; &lt;/span&gt;--foreground&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;SHELL&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;.SHELLFLAGS&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;\&lt;/span&gt;
&lt;span class="s2"&gt;		while ! docker-compose exec -T &amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;host&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot; docker ps; do sleep 0.1; done&amp;quot;&lt;/span&gt;
&lt;span class="c"&gt;# Load the built image into the deployment host Docker daemons&lt;/span&gt;
&lt;span class="w"&gt;	    &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;save&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bar-company/foo-app:dev&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;		&lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-T&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;{host}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;load
&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="nf"&gt;foo-host-corge/.env&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;POSTGRES_PASSWORD=&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;(apg -M NCL -n 1)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="s2"&gt;&amp;quot;./&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;@&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Once it’ up and running we can see that the network topology, host names, and
containerized services and applications are running as they would in the real hosted
deployment:&lt;/p&gt;
&lt;div class="highlight-shell-session notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;make&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec -T foo-host-corge docker-compose up -d&lt;/span&gt;
&lt;span class="go"&gt;foo-host-corge_foo-app_1 is up-to-date&lt;/span&gt;
&lt;span class="go"&gt;foo-host-corge_postgres_1 is up-to-date&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec -T foo-host-grault docker-compose up -d&lt;/span&gt;
&lt;span class="go"&gt;foo-host-grault_redis_1 is up-to-date&lt;/span&gt;
&lt;span class="go"&gt;foo-host-grault_foo-app_1 is up-to-date&lt;/span&gt;
&lt;span class="go"&gt;+ sleep 1&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec -T foo-host-corge docker-compose ps&lt;/span&gt;
&lt;span class="go"&gt;          Name                         Command               State           Ports&lt;/span&gt;
&lt;span class="go"&gt;-------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="go"&gt;foo-host-corge_foo-app_1    python -m http.server --di ...   Up      0.0.0.0:80-&amp;gt;80/tcp&lt;/span&gt;
&lt;span class="go"&gt;foo-host-corge_postgres_1   docker-entrypoint.sh postgres    Up      0.0.0.0:5432-&amp;gt;5432/tcp&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec -T foo-host-grault docker-compose ps&lt;/span&gt;
&lt;span class="go"&gt;          Name                         Command               State           Ports&lt;/span&gt;
&lt;span class="go"&gt;-------------------------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="go"&gt;foo-host-grault_foo-app_1   python -m http.server --di ...   Up      0.0.0.0:80-&amp;gt;80/tcp&lt;/span&gt;
&lt;span class="go"&gt;foo-host-grault_redis_1     docker-entrypoint.sh redis ...   Up      0.0.0.0:6379-&amp;gt;6379/tcp&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-corge docker-compose exec foo-app nc -vz redis 6379&lt;/span&gt;
&lt;span class="go"&gt;Ncat: Version 7.70 ( https://nmap.org/ncat )&lt;/span&gt;
&lt;span class="go"&gt;Ncat: Connected to 10.81.82.101:6379.&lt;/span&gt;
&lt;span class="go"&gt;Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-grault docker-compose exec foo-app nc -vz postgres 5432&lt;/span&gt;
&lt;span class="go"&gt;Ncat: Version 7.70 ( https://nmap.org/ncat )&lt;/span&gt;
&lt;span class="go"&gt;Ncat: Connected to 10.81.82.100:5432.&lt;/span&gt;
&lt;span class="go"&gt;Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.&lt;/span&gt;
&lt;span class="go"&gt;+ sudo rm -rfv &amp;#39;./var/lib/foo-data/*&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;+ ls -al ./var/lib/foo-data/&lt;/span&gt;
&lt;span class="go"&gt;total 8&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 2 root root 4096 Apr  5 08:49 .&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 5 root root 4096 Apr  5 08:45 ..&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-corge ls -al /home/ec2-user/foo-data/&lt;/span&gt;
&lt;span class="go"&gt;total 8&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x    2 root     root          4096 Apr  5 15:49 .&lt;/span&gt;
&lt;span class="go"&gt;drwxr-sr-x    1 ec2-user ec2-user      4096 Apr  5 15:45 ..&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-grault ls -al /home/ec2-user/foo-data/&lt;/span&gt;
&lt;span class="go"&gt;total 8&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x    2 root     root          4096 Apr  5 15:49 .&lt;/span&gt;
&lt;span class="go"&gt;drwxr-sr-x    1 ec2-user ec2-user      4096 Apr  5 15:45 ..&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-corge docker-compose exec foo-app ls -al /srv/foo-data/&lt;/span&gt;
&lt;span class="go"&gt;total 8&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 2 root root 4096 Apr  5 15:49 .&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 1 root root 4096 Apr  5 15:45 ..&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-grault docker-compose exec foo-app ls -al /srv/foo-data/&lt;/span&gt;
&lt;span class="go"&gt;total 8&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 2 root root 4096 Apr  5 15:49 .&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 1 root root 4096 Apr  5 15:45 ..&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-grault docker-compose exec foo-app test &amp;#39;!&amp;#39; -e /srv/foo-data/bar.txt&lt;/span&gt;
&lt;span class="go"&gt;+ sudo touch ./var/lib/foo-data/bar.txt&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-corge docker-compose exec foo-app ls -al /srv/foo-data/&lt;/span&gt;
&lt;span class="go"&gt;total 8&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 2 root root 4096 Apr  5 15:50 .&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 1 root root 4096 Apr  5 15:45 ..&lt;/span&gt;
&lt;span class="go"&gt;-rw-r--r-- 1 root root    0 Apr  5 15:50 bar.txt&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-grault docker-compose exec foo-app ls -al /srv/foo-data/&lt;/span&gt;
&lt;span class="go"&gt;total 8&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 2 root root 4096 Apr  5 15:50 .&lt;/span&gt;
&lt;span class="go"&gt;drwxr-xr-x 1 root root 4096 Apr  5 15:45 ..&lt;/span&gt;
&lt;span class="go"&gt;-rw-r--r-- 1 root root    0 Apr  5 15:50 bar.txt&lt;/span&gt;
&lt;span class="go"&gt;+ docker-compose exec foo-host-grault docker-compose exec foo-app test -e /srv/foo-data/bar.txt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;There you have it.  &lt;a class="reference external" href="https://gitlab.com/rpatterson/dind-reproduce-deploys"&gt;The demo code is publicly available&lt;/a&gt;.  I think we can find more
uses for DinD.  In particular, I have always found local development clean build issues
to be a persistent plague: “It worked for me when I committed it!”.  Next up I’m working
on using DinD as a route to a generic local clean build test.&lt;/p&gt;
&lt;/section&gt;
</content>
    <link href="https://www.rpatterson.net/blog/dind-reproduce-deploys/"/>
    <summary>Debugging deployment issues locally by falling down the Docker-in-Docker (DinD)
rabbit hole.</summary>
    <category term="DinD" label="DinD"/>
    <category term="Docker" label="Docker"/>
    <category term="docker-compose" label="docker-compose"/>
    <published>2021-04-09T00:00:00+00:00</published>
  </entry>
</feed>
