<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Celso Nery</title>
    <description>The latest articles on DEV Community by Celso Nery (@celsonery).</description>
    <link>https://dev.to/celsonery</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F416745%2F74d78e44-1418-4d26-89f1-06099837bf0d.jpg</url>
      <title>DEV Community: Celso Nery</title>
      <link>https://dev.to/celsonery</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/celsonery"/>
    <language>en</language>
    <item>
      <title>Part 6: Automating with Docker Compose</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:16:51 +0000</pubDate>
      <link>https://dev.to/celsonery/part-6-orchestrating-with-docker-compose-4c5o</link>
      <guid>https://dev.to/celsonery/part-6-orchestrating-with-docker-compose-4c5o</guid>
      <description>&lt;p&gt;🇧🇷 &lt;a href="https://dev.to/celsonery/parte-6-orquestrando-com-docker-compose-3545"&gt;Artigo em português aqui&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Docker — Part 6: Automating with Docker Compose
&lt;/h1&gt;

&lt;p&gt;Throughout this series, we've covered containers, volumes, networks, and image management — always using individual commands like &lt;code&gt;docker run&lt;/code&gt;, &lt;code&gt;docker network create&lt;/code&gt;, &lt;code&gt;docker volume create&lt;/code&gt;, etc. That works, but it becomes tedious (and error-prone) once an application starts depending on multiple services. That's where &lt;strong&gt;Docker Compose&lt;/strong&gt; comes in: it lets you describe all of this configuration in a single declarative file, making the process cleaner, easier to repeat, and easier to version in a Git repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating your docker-compose.yaml
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A minimal docker-compose.yaml
&lt;/h3&gt;

&lt;p&gt;The simplest possible structure, running a single service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpd&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is already equivalent to running &lt;code&gt;docker run -p 80:80 httpd&lt;/code&gt; — but in a declarative, reapplyable, and easily versioned way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a volume
&lt;/h3&gt;

&lt;p&gt;To persist that service's data (as we saw in Part 3 of this series), just add a &lt;code&gt;volumes&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpd&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web-data:/usr/local/apache2/htdocs&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the volume needs to be declared in two places: referenced inside the service (&lt;code&gt;volumes:&lt;/code&gt; under &lt;code&gt;web&lt;/code&gt;) and defined in the root-level &lt;code&gt;volumes:&lt;/code&gt; section at the end of the file — that's where Compose actually creates the named volume.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a network
&lt;/h3&gt;

&lt;p&gt;Likewise, you can declare custom networks (covered in Part 4):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpd&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web-data:/usr/local/apache2/htdocs&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In practice, when you don't explicitly declare a network, Compose already creates a default network for the project automatically, allowing services within the same &lt;code&gt;docker-compose.yaml&lt;/code&gt; to see each other by name. Declaring networks manually is worth it when you need more than one isolated network, or want to connect services across different Compose files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Bringing up the containers
&lt;/h2&gt;

&lt;p&gt;To create and start all the services defined in the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like with &lt;code&gt;docker run&lt;/code&gt;, the terminal stays "stuck," showing the logs of all services. To run it in the background:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tearing down the containers
&lt;/h2&gt;

&lt;p&gt;To stop and remove the containers and networks, while (by default) preserving the volumes created by Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;By default, &lt;code&gt;docker compose down&lt;/code&gt; &lt;strong&gt;does not remove volumes&lt;/strong&gt; — this prevents accidental data loss. If you want to remove volumes too, use &lt;code&gt;docker compose down -v&lt;/code&gt; (with caution).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Bringing multiple containers together: App + Database + Redis
&lt;/h2&gt;

&lt;p&gt;Compose's real power shows up when an application depends on multiple services working together. A common example: an Nginx proxy in front, an application, a MySQL database, and a Redis cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/conf.d/default.conf:ro&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp:1.0.0&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DB_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
      &lt;span class="na"&gt;DB_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appuser&lt;/span&gt;
      &lt;span class="na"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apppassword&lt;/span&gt;
      &lt;span class="na"&gt;REDIS_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:8.0&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rootpassword&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appdb&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appuser&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apppassword&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db-data:/var/lib/mysql&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:alpine&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few important points from this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;depends_on&lt;/code&gt;&lt;/strong&gt;: defines the startup order of the containers (&lt;code&gt;app&lt;/code&gt; only starts after &lt;code&gt;db&lt;/code&gt; and &lt;code&gt;redis&lt;/code&gt;). Note this only guarantees the &lt;em&gt;starting&lt;/em&gt; order of the container, not that the internal service (like MySQL) is already ready to accept connections — for that, the application usually needs to implement some retry logic on the database connection;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment variables&lt;/strong&gt; (&lt;code&gt;environment&lt;/code&gt;): used to configure the application and MySQL without needing to modify images or hardcode values;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;db-data&lt;/code&gt;&lt;/strong&gt;: a named volume ensuring MySQL's data survives container restarts and recreations;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;app-network&lt;/code&gt;&lt;/strong&gt;: all services share the same network, letting them communicate with each other by service name (&lt;code&gt;db&lt;/code&gt;, &lt;code&gt;redis&lt;/code&gt;) instead of fixed IPs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bringing everything up at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a single command, Compose creates the network, the volumes, and brings up all four containers already connected and ready to talk to each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Series wrap-up
&lt;/h2&gt;

&lt;p&gt;Throughout this series, we covered the complete day-to-day Docker lifecycle: installation, essential CLI commands, data persistence with volumes, container-to-container communication via networks, image management and publishing, and finally, orchestrating multiple services with Docker Compose. With this foundation, you now have everything you need to run containerized applications professionally — whether in a local development environment or on a production server.&lt;/p&gt;

&lt;p&gt;For anyone looking to go beyond a single host, the natural next step is &lt;strong&gt;Kubernetes&lt;/strong&gt; — which solves the same orchestration problems, but at scale, distributing containers across multiple servers.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>compose</category>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>Part 5: Managing Images</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:15:22 +0000</pubDate>
      <link>https://dev.to/celsonery/part-5-managing-images-5137</link>
      <guid>https://dev.to/celsonery/part-5-managing-images-5137</guid>
      <description>&lt;p&gt;🇧🇷 &lt;a href="https://dev.to/celsonery/parte-5-gerenciando-imagens-ble"&gt;Artigo em português aqui&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Docker — Part 5: Managing Images
&lt;/h1&gt;

&lt;p&gt;In Part 4 of this series, we covered how containers communicate through networks. Now let's tackle the lifecycle of Docker &lt;strong&gt;images&lt;/strong&gt;: how to build your own, list the ones already available locally, version them correctly, and publish them to a registry — whether Docker Hub or a private registry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building an image
&lt;/h2&gt;

&lt;p&gt;To build an image from a &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;image_name&amp;gt;:&amp;lt;version&amp;gt; &lt;span class="nt"&gt;-f&lt;/span&gt; dockerfile &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t &amp;lt;image_name&amp;gt;:&amp;lt;version&amp;gt;&lt;/code&gt;: sets the name and tag (version) of the resulting image; if the version is released, a 'latest' version will be created;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f dockerfile&lt;/code&gt;: specifies which Dockerfile to use (useful when you have multiple Dockerfiles in the same directory, or a non-default filename); if there is only one Dockerfile at the project root, this argument can be omitted;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt;: sets the &lt;strong&gt;build context&lt;/strong&gt; — the directory whose contents become available to instructions like &lt;code&gt;COPY&lt;/code&gt; and &lt;code&gt;ADD&lt;/code&gt; inside the Dockerfile.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Dockerfile example:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apk upgrade &lt;span class="nt"&gt;--no-cache&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./index.html ./&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "nginx", "-g", "daemon off;" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM&lt;/code&gt;: Specifies the base image to be used.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN&lt;/code&gt;: Commands to execute in order to build the application before building the image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR&lt;/code&gt;: Specifies the internal location within the image where operations are currently taking place.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY&lt;/code&gt;: Command to copy files from the local application into the Docker image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXPOSE&lt;/code&gt;: Specifies the port the container will listen on.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD&lt;/code&gt;: Command for the final execution of the application. (In this case, I am running Nginx).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Listing images
&lt;/h2&gt;

&lt;p&gt;To see all images already downloaded or built locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Versioning images (tag)
&lt;/h2&gt;

&lt;p&gt;Before publishing an image to a registry, you generally need to "tag" it with the full destination address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker tag &amp;lt;local_image_name&amp;gt;:&amp;lt;version&amp;gt; &amp;lt;remote_registry&amp;gt;/&amp;lt;remote_image_name&amp;gt;:&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, tagging a local &lt;code&gt;myapp:1.0.0&lt;/code&gt; image for Docker Hub, under the user &lt;code&gt;celsonery&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker tag myapp:1.0.0 celsonery/myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or for a private registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker tag myapp:1.0.0 registry.yourcompany.com/myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;It's considered good practice to use &lt;strong&gt;semantic versioning&lt;/strong&gt; in your tags (&lt;code&gt;1.0.0&lt;/code&gt;, &lt;code&gt;1.0.1&lt;/code&gt;, &lt;code&gt;1.1.0&lt;/code&gt;) instead of relying solely on the &lt;code&gt;latest&lt;/code&gt; tag, since &lt;code&gt;latest&lt;/code&gt; doesn't indicate exactly which version is running in production.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Removing images
&lt;/h2&gt;

&lt;p&gt;To remove a specific image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker image &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;image_name&amp;gt;:&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cleaning up unused images
&lt;/h2&gt;

&lt;p&gt;Intermediate images and images no longer referenced by any container tend to pile up over time, taking up disk space. To clean up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker image prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publishing an image (push)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;To publish an image, you must first authenticate with a registry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Docker Hub (default)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Private registry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the destination isn't Docker Hub, you need to provide the server address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker login registry.yourcompany.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push to Docker Hub
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker push &amp;lt;image_name&amp;gt;:&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push to a private registry
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker push &amp;lt;registry&amp;gt;/&amp;lt;image_name&amp;gt;:&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Remember: the image needs to have been &lt;strong&gt;tagged&lt;/strong&gt; (previous step) with the full destination registry address before the &lt;code&gt;push&lt;/code&gt; — otherwise, Docker will try to send it to Docker Hub by default.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;With the complete image lifecycle covered — build, tag, push —, you can now distribute your own applications as versioned images. In &lt;strong&gt;Part 6&lt;/strong&gt;, the last of this series, we'll bring everything we've covered together (volumes, networks, multiple containers) using &lt;strong&gt;Docker Compose&lt;/strong&gt;, making it much simpler and more organized to manage applications with multiple services.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in Part 6.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>Part 4: Working with Networks</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:13:48 +0000</pubDate>
      <link>https://dev.to/celsonery/part-4-working-with-networks-32po</link>
      <guid>https://dev.to/celsonery/part-4-working-with-networks-32po</guid>
      <description>&lt;p&gt;🇧🇷 &lt;a href="https://dev.to/celsonery/docker-para-desenvolvedores-parte-4-trabalhando-com-redes-2c70"&gt;Artigo em português aqui&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Docker — Part 4: Working with Networks
&lt;/h1&gt;

&lt;p&gt;In Part 3 of this series, we covered persisting data with volumes. Now let's tackle another fundamental pillar of multi-container applications: &lt;strong&gt;networking&lt;/strong&gt;. When an application depends on several services (for example, an API that needs to talk to a database), those containers need to be able to communicate with each other — and that's what Docker networks make possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listing networks
&lt;/h2&gt;

&lt;p&gt;Docker already creates a few default networks on installation (&lt;code&gt;bridge&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;). To list all existing networks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a network
&lt;/h2&gt;

&lt;p&gt;To create a custom network, isolated from the others:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network create &amp;lt;network_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Containers connected to the same custom network can communicate with each other using the &lt;strong&gt;container name&lt;/strong&gt; as the hostname — no need to discover or hardcode IP addresses manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspecting a network
&lt;/h2&gt;

&lt;p&gt;To see details about a network — such as the IP range, driver used, and which containers are connected to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network inspect &amp;lt;network_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running a container already connected to a network
&lt;/h2&gt;

&lt;p&gt;To create a container and connect it to a specific network right at creation time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--net&lt;/span&gt; &amp;lt;network_name&amp;gt; httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connecting a running container to a network
&lt;/h2&gt;

&lt;p&gt;If the container is already running and you want to add it to an additional network (a container can belong to multiple networks at once):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network connect &lt;span class="nt"&gt;--ip&lt;/span&gt; 192.168.100.10 &amp;lt;network_name&amp;gt; httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--ip&lt;/code&gt; flag lets you pin a specific IP for the container within that network — useful when other applications need a predictable address to connect to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disconnecting a container from a network
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network disconnect &amp;lt;network_name&amp;gt; httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Removing a network
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;network_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A network can only be removed if no container is currently connected to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cleaning up unused networks
&lt;/h2&gt;

&lt;p&gt;Just like with volumes, it's common to accumulate orphaned networks over time. To remove all networks not currently used by any container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Running isolated containers without a custom network works fine for quick tests — but as soon as an application needs multiple services talking to each other (app + database + cache, for example), custom networks stop being optional. They provide isolation (containers from different projects can't see each other by default) and simple name-based communication, without relying on manually managed fixed IPs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;With volumes for persistence and networks for communication between containers, we now have the two fundamental pieces needed to run multi-service applications. In &lt;strong&gt;Part 5&lt;/strong&gt; of this series, we'll cover &lt;strong&gt;image management&lt;/strong&gt;: how to build, version (tag), and publish your own images to a registry.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in Part 5.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>Part 3: Persisting Data with Volumes</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:12:00 +0000</pubDate>
      <link>https://dev.to/celsonery/part-3-persisting-data-with-volumes-1ig3</link>
      <guid>https://dev.to/celsonery/part-3-persisting-data-with-volumes-1ig3</guid>
      <description>&lt;p&gt;🇧🇷 &lt;a href="https://dev.to/celsonery/parte-3-persistindo-dados-com-volumes-1mk4"&gt;Artigo em português aqui&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Docker — Part 3: Persisting Data with Volumes
&lt;/h1&gt;

&lt;p&gt;In Part 2 of this series, we covered the essential commands for operating containers day to day. But there's an important detail: by default, data written inside a container is &lt;strong&gt;ephemeral&lt;/strong&gt; — if the container is removed, that data disappears with it. For stateful applications (databases, user uploads, configuration files), that's a problem. That's what &lt;strong&gt;volumes&lt;/strong&gt; exist to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bind mount vs. Volume
&lt;/h2&gt;

&lt;p&gt;There are two main ways to persist data outside a container's lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bind mount&lt;/strong&gt;: mounts a specific folder from the &lt;strong&gt;host&lt;/strong&gt; (the machine running Docker) inside the container. You have full control over where the data lives on the host, but you become more dependent on that specific machine's folder structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume&lt;/strong&gt;: managed by Docker itself, stored in an internal area (&lt;code&gt;/var/lib/docker/volumes/&lt;/code&gt; on Linux). This is the recommended approach for most cases, since it's more portable across environments and easier to back up, inspect, and clean up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article focuses on &lt;strong&gt;volumes&lt;/strong&gt; — the recommended approach for professional use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a volume
&lt;/h2&gt;

&lt;p&gt;To create a named volume that will store an application's data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create vol_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Listing volumes
&lt;/h2&gt;

&lt;p&gt;To see all volumes that already exist on the system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inspecting a volume
&lt;/h2&gt;

&lt;p&gt;To see details about a specific volume — such as the actual path where the data is stored on the host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume inspect vol_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running a container with a volume &lt;code&gt;-v&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using a bind mount
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; local_folder:remote_folder httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;local_folder&lt;/code&gt; is an absolute path on the host (for example, &lt;code&gt;/home/celso/data&lt;/code&gt;), and &lt;code&gt;remote_folder&lt;/code&gt; is the path inside the container where that data should appear (for example, &lt;code&gt;/var/www/htdocs/&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a created volume
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; volume_name:remote_folder httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;volume_name&lt;/code&gt; is the name of the volume created earlier with &lt;code&gt;docker volume create&lt;/code&gt; — Docker handles where that data is physically stored.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing a volume
&lt;/h2&gt;

&lt;p&gt;If any container is still using the volume, you'll need to remove the container first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;container_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, to remove the volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;rm &lt;/span&gt;vol_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cleaning up unused volumes
&lt;/h2&gt;

&lt;p&gt;Over time, it's common to accumulate orphaned volumes (created by containers that have since been removed). To clean up all volumes not currently used by any container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ This command permanently removes the data of any volume not referenced by an active container — confirm before running this on an environment with important data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using NFS volumes
&lt;/h2&gt;

&lt;p&gt;In environments with multiple Docker hosts (or when you want to share data across different servers), you can create a volume pointing to an &lt;strong&gt;NFS&lt;/strong&gt; share instead of local storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create &lt;span class="nt"&gt;--opt&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nfs &lt;span class="nt"&gt;--opt&lt;/span&gt; &lt;span class="nv"&gt;o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.0.0.35,rw,nfsvers&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nt"&gt;--opt&lt;/span&gt; &lt;span class="nv"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:/home/nfsshare nfs-volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;type=nfs&lt;/code&gt;: sets the volume driver to NFS;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;o=addr=10.0.0.35,rw,nfsvers=4&lt;/code&gt;: NFS server address and mount options (read/write, protocol version);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;device=:/home/nfsshare&lt;/code&gt;: path exported by the NFS server;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nfs-volume&lt;/code&gt;: name given to the volume in Docker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially useful in scenarios where multiple containers (possibly on different hosts) need access to the same shared data set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;With volumes handling data persistence, the next challenge is communication &lt;strong&gt;between&lt;/strong&gt; containers — especially when an application depends on multiple services (for example, an API that needs to talk to a database). In &lt;strong&gt;Part 4&lt;/strong&gt; of this series, we'll look at how to create and manage &lt;strong&gt;networks&lt;/strong&gt; in Docker.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in Part 4.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>volumes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Part 2: Essential CLI Commands</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:10:25 +0000</pubDate>
      <link>https://dev.to/celsonery/part-2-essential-cli-commands-41c1</link>
      <guid>https://dev.to/celsonery/part-2-essential-cli-commands-41c1</guid>
      <description>&lt;p&gt;🇧🇷 &lt;a href="https://dev.to/celsonery/parte-2-comandos-essenciais-da-cli-i3a"&gt;Artigo em português aqui&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Docker — Part 2: Essential CLI Commands
&lt;/h1&gt;

&lt;p&gt;In Part 1 of this series, we installed Docker on Debian and ran our first container. Now let's cover the commands you'll use day to day to manage containers: running, listing, entering, stopping, removing, tailing logs, and monitoring resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running a container
&lt;/h2&gt;

&lt;p&gt;The most basic command is &lt;code&gt;docker run&lt;/code&gt;, which creates and starts a container from a builded image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--rm&lt;/code&gt;: automatically removes the container as soon as it stops (useful for tests, avoiding a pile-up of stopped containers);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:80&lt;/code&gt;: maps port 8080 of the host to port 80 of the container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running this command keeps the terminal "stuck," showing the container's logs in the foreground. To free up the terminal and run it in the background, use the &lt;code&gt;-d&lt;/code&gt; (daemon) flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Listing containers
&lt;/h2&gt;

&lt;p&gt;To see the containers that are &lt;strong&gt;currently running&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see &lt;strong&gt;all&lt;/strong&gt; containers, including the ones that have already stopped, use the &lt;code&gt;-a&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for spotting stopped containers that might not have been removed (because they weren't run with the &lt;code&gt;--rm&lt;/code&gt; flag).&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting a container
&lt;/h2&gt;

&lt;p&gt;To interactively enter a running container (opening a shell):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container name or ID&amp;gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If the image is Alpine-based (as many lightweight production images are), it usually doesn't have &lt;code&gt;bash&lt;/code&gt; installed — use &lt;code&gt;ash&lt;/code&gt; instead:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container name or ID&amp;gt; ash
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Now you can run any command inside container to check &lt;code&gt;cat /etc/os-release&lt;/code&gt; ou &lt;code&gt;env&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also run a specific command without opening an interactive session — for example, to check an environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container name or ID&amp;gt; &lt;span class="nb"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This way, you won't need to enter the container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stopping and removing containers
&lt;/h2&gt;

&lt;p&gt;To stop a running container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker stop &amp;lt;container name or ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stopping doesn't remove the container — it continues to exist (stopped), until you explicitly remove it or it was created with &lt;code&gt;--rm&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;To remove it manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;container name or ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tailing logs
&lt;/h2&gt;

&lt;p&gt;Containers typically write their logs to &lt;code&gt;stdout&lt;/code&gt;/&lt;code&gt;stderr&lt;/code&gt;, and Docker captures that automatically. To view them (and follow in real time, like &lt;code&gt;tail -f&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;container name or ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the &lt;code&gt;-f&lt;/code&gt; flag, the command just prints the existing logs up to that point, without continuing to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring resources
&lt;/h2&gt;

&lt;p&gt;To see, in real time, the CPU, memory, disk I/O, and network usage of all running containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker stats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command is useful for quickly identifying containers consuming excessive resources, without needing external monitoring tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;With the essential CLI commands in hand, you can already operate containers day to day with confidence. But so far, data inside containers is ephemeral — if the container is removed, the data goes with it. In &lt;strong&gt;Part 3&lt;/strong&gt; of this series, we'll solve that with &lt;strong&gt;volumes&lt;/strong&gt;, ensuring data persistence between runs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in Part 3.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Part 1: Installing on Debian</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:08:49 +0000</pubDate>
      <link>https://dev.to/celsonery/part-1-installing-on-debian-480h</link>
      <guid>https://dev.to/celsonery/part-1-installing-on-debian-480h</guid>
      <description>&lt;p&gt;🇧🇷 &lt;a href="https://dev.to/celsonery/docker-para-desenvolvedores-j48"&gt;Artigo em português aqui&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker for Devs — Part 1: Installing on Debian
&lt;/h1&gt;

&lt;p&gt;This is the first part of a series on using Docker day to day: installation, CLI usage, volumes, networks, image management, and Docker Compose. The goal is to start from scratch and build up to a complete, professional workflow with Docker.&lt;/p&gt;

&lt;p&gt;In this first part, we cover the complete installation on Debian — from scratch to running your first container.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use &lt;code&gt;sudo&lt;/code&gt; before the commands below if you're running them as a regular user (not root).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Updating the system
&lt;/h2&gt;

&lt;p&gt;Before installing any new package, update the package list and the system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt update&lt;/span&gt;
&lt;span class="c"&gt;# apt upgrade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing required packages
&lt;/h2&gt;

&lt;p&gt;A few packages are prerequisites for safely adding external repositories (GPG keys, HTTPS, etc.):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt install curl gnupg2 apt-transport-https software-properties-common ca-certificates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding the Docker repository
&lt;/h2&gt;

&lt;p&gt;Download and register Docker's official GPG key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the repository file at &lt;code&gt;/etc/apt/sources.list.d/docker.list&lt;/code&gt; and add this content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deb &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64 signed-by&lt;span class="o"&gt;=&lt;/span&gt;/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/debian bookworm stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Watch your Debian version:&lt;/strong&gt; the codename (&lt;code&gt;bookworm&lt;/code&gt;, in the example) needs to match your Debian version — &lt;code&gt;bookworm&lt;/code&gt; is Debian 12, &lt;code&gt;bullseye&lt;/code&gt; is Debian 11, &lt;code&gt;buster&lt;/code&gt; is Debian 10. To find out your installation's codename, run:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;

or

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/os-release
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;And replace &lt;code&gt;bookworm&lt;/code&gt; with the returned value, if you're on a different version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Container runtime: Docker or containerd?
&lt;/h2&gt;

&lt;p&gt;If the end goal is building a &lt;strong&gt;Kubernetes cluster&lt;/strong&gt;, it's worth pausing here: Kubernetes hasn't used Docker directly as its runtime since version 1.24 — it relies on &lt;strong&gt;containerd&lt;/strong&gt; (which, as it happens, already ships alongside the Docker Engine installation, but can also be installed standalone). If that's your case, skip straight to the &lt;a href="https://dev.to/celsonery/building-an-on-premise-kubernetes-cluster-part-2-installing-containerd-and-kubernetes-pe9"&gt;Kubernetes installation article&lt;/a&gt;, which covers installing containerd specifically for that scenario.&lt;/p&gt;

&lt;p&gt;If your goal is to use the &lt;strong&gt;full Docker Engine&lt;/strong&gt; (to run standalone containers, Docker Compose, etc.), continue with the steps below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Docker
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt update&lt;/span&gt;
&lt;span class="c"&gt;# apt install docker-ce&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you run into issues running containers with the latest version, you can install a previous version, such as 18.06.0:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt install docker-ce=18.06.0~ce~3-0~debian&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Configuring the daemon
&lt;/h2&gt;

&lt;p&gt;Create the &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; file with the following settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exec-opts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"native.cgroupdriver=systemd"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"log-driver"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"json-file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"log-opts"&lt;/span&gt;&lt;span class="p"&gt;:&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;&lt;span class="nl"&gt;"max-size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100m"&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;&lt;span class="nl"&gt;"storage-driver"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"overlay2"&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;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;code&gt;systemd&lt;/code&gt; as the cgroup driver (important for staying consistent with other &lt;code&gt;systemd&lt;/code&gt;-managed services on the system, including Kubernetes itself, if you install it later);&lt;/li&gt;
&lt;li&gt;Limits each container's log size to 100MB, preventing "noisy" containers from filling up the disk with logs;&lt;/li&gt;
&lt;li&gt;Uses the &lt;code&gt;overlay2&lt;/code&gt; storage driver, currently recommended for most use cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create the Docker systemd service override directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# mkdir -p /etc/systemd/system/docker.service.d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload and restart the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl daemon-reload
systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Allowing a regular user to use Docker
&lt;/h2&gt;

&lt;p&gt;By default, Docker commands require root privileges. To let a regular user run containers without needing &lt;code&gt;sudo&lt;/code&gt; for every command, add them to the &lt;code&gt;docker&lt;/code&gt; group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# usermod -aG docker $USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You need to log out and log back in (or restart your session) for the group change to take effect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Verifying the installation
&lt;/h2&gt;

&lt;p&gt;Confirm Docker is installed and working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output should look similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Client&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;18.06.0-ce&lt;/span&gt;
 &lt;span class="na"&gt;API version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="m"&gt;1.38&lt;/span&gt;
 &lt;span class="na"&gt;Go version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;go1.10.3&lt;/span&gt;
 &lt;span class="na"&gt;Git commit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;0ffa825&lt;/span&gt;
 &lt;span class="na"&gt;Built&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             &lt;span class="s"&gt;Wed Jul 18 19:09:33 &lt;/span&gt;&lt;span class="m"&gt;2018&lt;/span&gt;
 &lt;span class="na"&gt;OS/Arch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
 &lt;span class="na"&gt;Experimental&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="na"&gt;Server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;Engine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;18.06.0-ce&lt;/span&gt;
  &lt;span class="na"&gt;API version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;1.38 (minimum version 1.12)&lt;/span&gt;
  &lt;span class="na"&gt;Go version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;go1.10.3&lt;/span&gt;
  &lt;span class="na"&gt;Git commit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;0ffa825&lt;/span&gt;
  &lt;span class="na"&gt;Built&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;            &lt;span class="s"&gt;Wed Jul 18 19:07:38 &lt;/span&gt;&lt;span class="m"&gt;2018&lt;/span&gt;
  &lt;span class="na"&gt;OS/Arch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
  &lt;span class="na"&gt;Experimental&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The version shown will vary depending on what's installed on your system — the example above reflects version 18.06.0.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Running your first container
&lt;/h2&gt;

&lt;p&gt;The classic test, using Docker's official example image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, for a slightly more tangible test, spinning up an Apache web server (httpd) on port 80:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm it worked, open your browser and access the host machine's IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Apache's default page shows up, the Docker installation is complete and working correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;With Docker installed, configured with the correct cgroup driver, and successfully tested, the server is now ready for day-to-day container work. In &lt;strong&gt;Part 2&lt;/strong&gt; of this series, we'll explore the most commonly used Docker CLI commands: &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;logs&lt;/code&gt;, and &lt;code&gt;stats&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in Part 2.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>debian</category>
      <category>devops</category>
    </item>
    <item>
      <title>Parte 6: Automatizando com Docker Compose</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:01:59 +0000</pubDate>
      <link>https://dev.to/celsonery/parte-6-orquestrando-com-docker-compose-3545</link>
      <guid>https://dev.to/celsonery/parte-6-orquestrando-com-docker-compose-3545</guid>
      <description>&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/celsonery/part-6-orchestrating-with-docker-compose-4c5o"&gt;English version here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker para Desenvolvedores — Parte 6: Automatizando com Docker Compose
&lt;/h1&gt;

&lt;p&gt;Ao longo desta série, vimos containers, volumes, redes e gerenciamento de imagens — sempre usando comandos individuais do &lt;code&gt;docker run&lt;/code&gt;, &lt;code&gt;docker network create&lt;/code&gt;, &lt;code&gt;docker volume create&lt;/code&gt;, etc. Isso funciona, mas se torna trabalhoso (e propenso a erros) conforme uma aplicação passa a depender de múltiplos serviços. É aí que o &lt;strong&gt;Docker Compose&lt;/strong&gt; entra: ele permite descrever toda essa configuração em um único arquivo declarativo, tornando o processo mais limpo, mais fácil de repetir e de versionar em um repositório Git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando seu docker-compose.yaml
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Um docker-compose.yaml mínimo
&lt;/h3&gt;

&lt;p&gt;A estrutura mais simples possível, rodando um único serviço:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpd&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:80"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso já é equivalente a rodar &lt;code&gt;docker run -p 8080:80 httpd&lt;/code&gt; — mas de forma declarativa, reaplicável e fácil de versionar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Acrescentando um volume
&lt;/h3&gt;

&lt;p&gt;Para persistir dados desse serviço (como vimos na Parte 3 desta série), basta adicionar uma seção &lt;code&gt;volumes&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpd&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web-data:/usr/local/apache2/htdocs&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repare que o volume precisa ser declarado em dois lugares: referenciado dentro do serviço (&lt;code&gt;volumes:&lt;/code&gt; dentro de &lt;code&gt;web&lt;/code&gt;) e definido na seção raiz &lt;code&gt;volumes:&lt;/code&gt; no final do arquivo — é ali que o Compose realmente cria o volume nomeado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Acrescentando uma rede
&lt;/h3&gt;

&lt;p&gt;Da mesma forma, é possível declarar redes customizadas (vistas na Parte 4):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpd&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web-data:/usr/local/apache2/htdocs&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Na prática, quando você não declara uma rede explicitamente, o Compose já cria uma rede padrão para o projeto automaticamente, permitindo que os serviços do mesmo &lt;code&gt;docker-compose.yaml&lt;/code&gt; se enxerguem entre si pelo nome. Declarar redes manualmente vale a pena quando você precisa de mais de uma rede isolada, ou quer conectar serviços de arquivos Compose diferentes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Subindo os containers
&lt;/h2&gt;

&lt;p&gt;Para criar e iniciar todos os serviços definidos no arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim como no &lt;code&gt;docker run&lt;/code&gt;, o terminal fica preso mostrando os logs de todos os serviços. Para rodar em segundo plano:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Derrubando os containers
&lt;/h2&gt;

&lt;p&gt;Para parar e remover os containers, redes e (por padrão) preservar os volumes criados pelo Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Por padrão, &lt;code&gt;docker compose down&lt;/code&gt; &lt;strong&gt;não remove volumes&lt;/strong&gt; — isso evita perda acidental de dados. Se você quiser remover os volumes também, use &lt;code&gt;docker compose down -v&lt;/code&gt; (com cautela).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Juntando vários containers: App + Database + Redis
&lt;/h2&gt;

&lt;p&gt;O verdadeiro poder do Compose aparece quando uma aplicação depende de múltiplos serviços trabalhando juntos. Um exemplo comum: um proxy Nginx na frente, uma aplicação, um banco de dados MySQL e um cache Redis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/conf.d/default.conf:ro&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp:1.0.0&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DB_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
      &lt;span class="na"&gt;DB_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appuser&lt;/span&gt;
      &lt;span class="na"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apppassword&lt;/span&gt;
      &lt;span class="na"&gt;REDIS_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:8.0&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rootpassword&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appdb&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appuser&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apppassword&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db-data:/var/lib/mysql&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:alpine&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alguns pontos importantes desse exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;depends_on&lt;/code&gt;&lt;/strong&gt;: define a ordem de inicialização dos containers (o &lt;code&gt;app&lt;/code&gt; só sobe depois do &lt;code&gt;db&lt;/code&gt; e do &lt;code&gt;redis&lt;/code&gt;). Vale notar que isso garante apenas a ordem de &lt;em&gt;início&lt;/em&gt; do container, não que o serviço interno (como o MySQL) já esteja pronto para aceitar conexões — para isso, a aplicação normalmente precisa implementar alguma lógica de retry na conexão com o banco;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variáveis de ambiente&lt;/strong&gt; (&lt;code&gt;environment&lt;/code&gt;): usadas para configurar a aplicação e o MySQL sem precisar alterar imagens ou hardcodar valores;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;db-data&lt;/code&gt;&lt;/strong&gt;: volume nomeado garantindo que os dados do MySQL sobrevivam a reinicializações e recriações do container;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;app-network&lt;/code&gt;&lt;/strong&gt;: todos os serviços compartilham a mesma rede, permitindo que se comuniquem entre si pelo nome do serviço (&lt;code&gt;db&lt;/code&gt;, &lt;code&gt;redis&lt;/code&gt;) em vez de IPs fixos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Subindo tudo de uma vez:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com um único comando, o Compose cria a rede, os volumes, e sobe os quatro containers já conectados e prontos para se comunicar entre si.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações finais da série
&lt;/h2&gt;

&lt;p&gt;Ao longo desta série, cobrimos o ciclo completo do Docker no dia a dia: instalação, comandos essenciais da CLI, persistência de dados com volumes, comunicação entre containers via redes, gerenciamento e publicação de imagens, e, por fim, orquestração de múltiplos serviços com Docker Compose. Com essa base, você já tem tudo o que precisa para rodar aplicações containerizadas de forma profissional — seja em um ambiente de desenvolvimento local, seja em um servidor de produção.&lt;/p&gt;

&lt;p&gt;Para quem quiser ir além de um único host, o próximo passo natural é o &lt;strong&gt;Kubernetes&lt;/strong&gt; — que resolve os mesmos problemas de orquestração, mas em escala, distribuindo containers entre múltiplos servidores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/celsonery/series/42627"&gt;Você pode encontrar uma série de artigo que fiz sobre kubernetes&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
      <category>compose</category>
    </item>
    <item>
      <title>Parte 5: Gerenciando Imagens</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 23:00:15 +0000</pubDate>
      <link>https://dev.to/celsonery/parte-5-gerenciando-imagens-ble</link>
      <guid>https://dev.to/celsonery/parte-5-gerenciando-imagens-ble</guid>
      <description>&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/celsonery/part-5-managing-images-5137"&gt;English version here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker para Desenvolvedores — Parte 5: Gerenciando Imagens
&lt;/h1&gt;

&lt;p&gt;Na Parte 4 desta série, vimos como containers se comunicam através de redes. Agora vamos abordar o ciclo de vida das &lt;strong&gt;imagens&lt;/strong&gt; Docker: como construir a sua própria, listar as que já existem localmente, versioná-las corretamente e publicá-las em um registry — seja o Docker Hub, seja um registry privado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Construindo uma imagem (build)
&lt;/h2&gt;

&lt;p&gt;Para construir uma imagem a partir de um &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;nome_da_imagem&amp;gt;:&amp;lt;versao&amp;gt; &lt;span class="nt"&gt;-f&lt;/span&gt; dockerfile &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t &amp;lt;nome_da_imagem&amp;gt;:&amp;lt;versao&amp;gt;&lt;/code&gt;: define o nome e a tag (versão) da imagem resultante; caso for emitida a versão será criada uma latest;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f dockerfile&lt;/code&gt;: indica o arquivo Dockerfile a ser usado (útil quando você tem múltiplos Dockerfiles no mesmo diretório, ou um nome de arquivo diferente do padrão); caso tenha somente um Dockerfile na raiz do projeto, este argumento pode ser omitido;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt;: define o &lt;strong&gt;contexto de build&lt;/strong&gt; — o diretório cujo conteúdo fica disponível para instruções como &lt;code&gt;COPY&lt;/code&gt; e &lt;code&gt;ADD&lt;/code&gt; dentro do Dockerfile.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Exemplo de um Dockerfile&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apk upgrade &lt;span class="nt"&gt;--no-cache&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./index.html ./&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "nginx", "-g", "daemon off;" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM&lt;/code&gt;: Informa a imagem base a ser usada.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN&lt;/code&gt;: Comandos para rodar para buildar a aplicação antes de buildar a imagem.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR&lt;/code&gt;: Informa local interno na imagem onde se está trabalhando no momento.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY&lt;/code&gt;: Comando para copiar arquivos da aplicação local para dentro da imagem docker.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXPOSE&lt;/code&gt;: Informa a porta que o container ira escutar.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD&lt;/code&gt;: Comando de execução final da aplicação. (Neste caso estou rodando o nginx).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Listando imagens
&lt;/h2&gt;

&lt;p&gt;Para ver todas as imagens já baixadas ou construídas localmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Versionando imagens (tag)
&lt;/h2&gt;

&lt;p&gt;Antes de publicar uma imagem em um registry, geralmente é preciso "marcá-la" (tag) com o endereço completo do destino:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker tag &amp;lt;nome_da_imagem_local&amp;gt;:&amp;lt;versao&amp;gt; &amp;lt;registro_remoto&amp;gt;/&amp;lt;nome_da_imagem_remoto&amp;gt;:&amp;lt;versao&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por exemplo, marcando uma imagem local &lt;code&gt;myapp:1.0.0&lt;/code&gt; para o Docker Hub, sob o usuário &lt;code&gt;celsonery&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker tag myapp:1.0.0 celsonery/myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou para um registry privado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker tag myapp:1.0.0 registry.suaempresa.com/myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;É considerada boa prática usar &lt;strong&gt;versionamento semântico&lt;/strong&gt; nas tags (&lt;code&gt;1.0.0&lt;/code&gt;, &lt;code&gt;1.0.1&lt;/code&gt;, &lt;code&gt;1.1.0&lt;/code&gt;) em vez de depender apenas da tag &lt;code&gt;latest&lt;/code&gt;, já que &lt;code&gt;latest&lt;/code&gt; não indica qual versão exata está rodando em produção.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Removendo imagens
&lt;/h2&gt;

&lt;p&gt;Para remover uma imagem específica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker image &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;nome_da_imagem&amp;gt;:&amp;lt;versao&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Limpando imagens não utilizadas
&lt;/h2&gt;

&lt;p&gt;Imagens intermediárias e não referenciadas por nenhum container tendem a se acumular ao longo do tempo, ocupando espaço em disco. Para limpar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker image prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publicando uma imagem (push)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Para publicar uma imagem, primeiramente é preciso autenticar-se em algum registry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Docker Hub (padrão)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Registry privado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quando o destino não é o Docker Hub, é preciso informar o endereço do servidor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker login registry.suaempresa.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push para o Docker Hub
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker push &amp;lt;nome_da_imagem&amp;gt;:&amp;lt;versao&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push para um registry privado
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker push &amp;lt;registry&amp;gt;/&amp;lt;nome_da_imagem&amp;gt;:&amp;lt;versao&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Lembre-se: a imagem precisa ter sido &lt;strong&gt;taggeada&lt;/strong&gt; (passo anterior) com o endereço completo do registro de destino antes do &lt;code&gt;push&lt;/code&gt; — caso contrário, o Docker tentará enviá-la para o Docker Hub por padrão.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Com o ciclo completo de imagens dominado — build, tag, push —, você já consegue distribuir suas próprias aplicações como imagens versionadas. Na &lt;strong&gt;Parte 6&lt;/strong&gt;, e última desta série, vamos juntar tudo o que vimos até aqui (volumes, redes, múltiplos containers) usando o &lt;strong&gt;Docker Compose&lt;/strong&gt;, tornando o gerenciamento de aplicações com múltiplos serviços muito mais simples e organizado.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continua na Parte 6.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
      <category>build</category>
    </item>
    <item>
      <title>Parte 4: Trabalhando com Redes</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 22:53:22 +0000</pubDate>
      <link>https://dev.to/celsonery/docker-para-desenvolvedores-parte-4-trabalhando-com-redes-2c70</link>
      <guid>https://dev.to/celsonery/docker-para-desenvolvedores-parte-4-trabalhando-com-redes-2c70</guid>
      <description>&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/celsonery/part-4-working-with-networks-32po"&gt;English version here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker para Desenvolvedores — Parte 4: Trabalhando com Redes
&lt;/h1&gt;

&lt;p&gt;Na Parte 3 desta série, vimos como persistir dados com volumes. Agora vamos abordar outro pilar fundamental de aplicações com múltiplos containers: a &lt;strong&gt;rede&lt;/strong&gt;. Quando uma aplicação depende de vários serviços (por exemplo, uma API que precisa conversar com um banco de dados), esses containers precisam conseguir se comunicar entre si — e é isso que as redes do Docker viabilizam.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listando redes
&lt;/h2&gt;

&lt;p&gt;O Docker já cria algumas redes padrão na instalação (&lt;code&gt;bridge&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;). Para listar as redes existentes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando uma rede
&lt;/h2&gt;

&lt;p&gt;Para criar uma rede customizada, isolada das demais:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network create &amp;lt;nome_da_rede&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Containers conectados à mesma rede customizada conseguem se comunicar entre si usando o &lt;strong&gt;nome do container&lt;/strong&gt; como hostname — sem precisar descobrir ou fixar endereços IP manualmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspecionando uma rede
&lt;/h2&gt;

&lt;p&gt;Para ver detalhes de uma rede — como o range de IPs, driver usado e quais containers estão conectados a ela:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network inspect &amp;lt;nome_da_rede&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rodando um container já conectado a uma rede
&lt;/h2&gt;

&lt;p&gt;Para criar um container e já conectá-lo a uma rede específica no momento da criação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--net&lt;/span&gt; &amp;lt;nome_da_rede&amp;gt; httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conectando um container já em execução a uma rede
&lt;/h2&gt;

&lt;p&gt;Se o container já está rodando e você quer adicioná-lo a uma rede adicional (um container pode pertencer a múltiplas redes simultaneamente):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network connect &lt;span class="nt"&gt;--ip&lt;/span&gt; 192.168.100.10 &amp;lt;nome_da_rede&amp;gt; httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A flag &lt;code&gt;--ip&lt;/code&gt; permite fixar um IP específico para o container dentro dessa rede — útil quando outras aplicações precisam de um endereço previsível para se conectar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Desconectando um container de uma rede
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network disconnect &amp;lt;nome_da_rede&amp;gt; httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Removendo uma rede
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;nome_da_rede&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Uma rede só pode ser removida se não houver nenhum container conectado a ela no momento.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Limpando redes não utilizadas
&lt;/h2&gt;

&lt;p&gt;Assim como acontece com volumes, é comum acumular redes órfãs ao longo do tempo. Para remover todas as redes que não estão sendo usadas por nenhum container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Por que isso importa
&lt;/h2&gt;

&lt;p&gt;Rodar containers isolados, sem uma rede customizada, funciona para testes rápidos — mas assim que uma aplicação precisa de múltiplos serviços conversando entre si (app + banco de dados + cache, por exemplo), redes customizadas deixam de ser opcionais. Elas garantem isolamento (containers de projetos diferentes não se enxergam por padrão) e comunicação simples por nome, sem depender de IPs fixos gerenciados manualmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Com volumes para persistência e redes para comunicação entre containers, já temos as duas peças fundamentais para rodar aplicações multi-serviço. Na &lt;strong&gt;Parte 5&lt;/strong&gt; desta série, vamos falar sobre &lt;strong&gt;gerenciamento de imagens&lt;/strong&gt;: como construir, versionar (tag) e publicar suas próprias imagens em um registry.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continua na Parte 5.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
      <category>network</category>
    </item>
    <item>
      <title>Parte 3: Persistindo Dados com Volumes</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 22:51:29 +0000</pubDate>
      <link>https://dev.to/celsonery/parte-3-persistindo-dados-com-volumes-1mk4</link>
      <guid>https://dev.to/celsonery/parte-3-persistindo-dados-com-volumes-1mk4</guid>
      <description>&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/celsonery/part-3-persisting-data-with-volumes-1ig3"&gt;English version here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker para Desenvolvedores — Parte 3: Persistindo Dados com Volumes
&lt;/h1&gt;

&lt;p&gt;Na Parte 2 desta série, vimos os comandos essenciais para operar containers no dia a dia. Mas há um detalhe importante: por padrão, os dados escritos dentro de um container são &lt;strong&gt;efêmeros&lt;/strong&gt; — se o container for removido, esses dados desaparecem junto. Para aplicações com estado (bancos de dados, uploads de usuários, arquivos de configuração), isso é um problema. É para resolver isso que existem os &lt;strong&gt;volumes&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bind mount x Volume
&lt;/h2&gt;

&lt;p&gt;Existem duas formas principais de persistir dados fora do ciclo de vida do container:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bind mount&lt;/strong&gt;: monta uma pasta específica do &lt;strong&gt;host&lt;/strong&gt; (a máquina onde o Docker roda) dentro do container. Você tem controle total sobre onde os dados ficam no host, mas fica mais dependente da estrutura de pastas daquela máquina específica.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume&lt;/strong&gt;: gerenciado pelo próprio Docker, armazenado em uma área interna (&lt;code&gt;/var/lib/docker/volumes/&lt;/code&gt; no Linux). É a forma recomendada para a maioria dos casos, pois é mais portável entre ambientes e mais fácil de fazer backup, inspecionar e limpar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este artigo foca em &lt;strong&gt;volumes&lt;/strong&gt; — a abordagem mais indicada para uso profissional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando um volume
&lt;/h2&gt;

&lt;p&gt;Para criar um volume nomeado, que vai armazenar os dados de uma aplicação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create nome_do_vol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Listando volumes
&lt;/h2&gt;

&lt;p&gt;Para ver todos os volumes já existentes no sistema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inspecionando um volume
&lt;/h2&gt;

&lt;p&gt;Para ver detalhes de um volume específico — como o caminho real onde os dados ficam armazenados no host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume inspect nome_do_vol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rodando um container com um volume &lt;code&gt;-v&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Usando bind mount
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; pasta_local:pasta_remota httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, &lt;code&gt;pasta_local&lt;/code&gt; é um caminho absoluto no host (por exemplo, &lt;code&gt;/home/celso/dados&lt;/code&gt;), e &lt;code&gt;pasta_remota&lt;/code&gt; é o caminho dentro do container onde esses dados devem aparecer (por exemplo, &lt;code&gt;/var/www/htdocs/&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Usando um volume criado
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; nome_do_volume:pasta_remota httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso, &lt;code&gt;nome_do_volume&lt;/code&gt; é o nome do volume criado anteriormente com &lt;code&gt;docker volume create&lt;/code&gt; — o Docker cuida de onde esses dados ficam fisicamente armazenados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removendo um volume
&lt;/h2&gt;

&lt;p&gt;Se algum container ainda estiver usando o volume, será preciso remover o container primeiro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;nome_do_container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois, para remover o volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;rm &lt;/span&gt;nome_do_vol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Limpando volumes não utilizados
&lt;/h2&gt;

&lt;p&gt;Com o tempo, é comum acumular volumes órfãos (criados por containers que já foram removidos). Para limpar todos os volumes que não estão sendo usados por nenhum container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Esse comando remove permanentemente os dados de qualquer volume não referenciado por um container ativo — confirme antes de rodar em um ambiente com dados importantes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Usando volumes NFS
&lt;/h2&gt;

&lt;p&gt;Em ambientes com múltiplos hosts Docker (ou quando você quer compartilhar dados entre diferentes servidores), é possível criar um volume que aponta para um compartilhamento &lt;strong&gt;NFS&lt;/strong&gt; em vez de armazenamento local:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create &lt;span class="nt"&gt;--opt&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nfs &lt;span class="nt"&gt;--opt&lt;/span&gt; &lt;span class="nv"&gt;o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.0.0.35,rw,nfsvers&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nt"&gt;--opt&lt;/span&gt; &lt;span class="nv"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:/home/nfsshare nfs-volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;type=nfs&lt;/code&gt;: define o driver de volume como NFS;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;o=addr=10.0.0.35,rw,nfsvers=4&lt;/code&gt;: endereço do servidor NFS e opções de montagem (leitura/escrita, versão do protocolo);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;device=:/home/nfsshare&lt;/code&gt;: caminho exportado pelo servidor NFS;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nfs-volume&lt;/code&gt;: nome dado ao volume no Docker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso é especialmente útil em cenários onde múltiplos containers (possivelmente em hosts diferentes) precisam acessar o mesmo conjunto de dados compartilhado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Com volumes garantindo persistência de dados, o próximo desafio é a comunicação &lt;strong&gt;entre&lt;/strong&gt; containers — especialmente quando uma aplicação depende de vários serviços (por exemplo, uma API que precisa falar com um banco de dados). Na &lt;strong&gt;Parte 4&lt;/strong&gt; desta série, vamos ver como criar e gerenciar &lt;strong&gt;redes&lt;/strong&gt; no Docker.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continua na Parte 4.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>volumes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Parte 2: Comandos Essenciais da CLI</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 22:45:46 +0000</pubDate>
      <link>https://dev.to/celsonery/parte-2-comandos-essenciais-da-cli-i3a</link>
      <guid>https://dev.to/celsonery/parte-2-comandos-essenciais-da-cli-i3a</guid>
      <description>&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/celsonery/part-2-essential-cli-commands-41c1"&gt;English version here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker para Desenvolvedores — Parte 2: Comandos Essenciais da CLI
&lt;/h1&gt;

&lt;p&gt;Na Parte 1 desta série, instalamos o Docker no Debian e rodamos nosso primeiro container. Agora vamos conhecer os comandos que você vai usar no dia a dia para gerenciar containers: rodar, listar, entrar, parar, remover, acompanhar logs e monitorar recursos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rodando um container
&lt;/h2&gt;

&lt;p&gt;O comando mais básico é o &lt;code&gt;docker run&lt;/code&gt;, que cria e inicia um container a partir de uma imagem pronta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--rm&lt;/code&gt;: remove o container automaticamente assim que ele parar (útil para testes, evitando acumular containers parados);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:80&lt;/code&gt;: mapeia a porta 8080 do host(sua máquina) para a porta 80 do container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rodando esse comando, o terminal fica "preso" mostrando os logs do container em primeiro plano. Para liberar o terminal e rodar em segundo plano, use a flag &lt;code&gt;-d&lt;/code&gt; (daemon):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Listando containers
&lt;/h2&gt;

&lt;p&gt;Para ver os containers que estão &lt;strong&gt;em execução&lt;/strong&gt; no momento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para ver &lt;strong&gt;todos&lt;/strong&gt; os containers, incluindo os que já pararam, use a flag &lt;code&gt;-a&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso é útil para identificar containers parados que talvez não tenham sido removidos (por não terem usado a flag &lt;code&gt;--rm&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Entrando em um container
&lt;/h2&gt;

&lt;p&gt;Para entrar interativamente em um container já em execução "abrindo um shell":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;nome ou ID &lt;span class="k"&gt;do &lt;/span&gt;container&amp;gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Se a imagem for baseada em Alpine (como muitas imagens leves de produção), ela geralmente não tem &lt;code&gt;bash&lt;/code&gt; instalado — use &lt;code&gt;ash&lt;/code&gt; no lugar:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;nome ou ID &lt;span class="k"&gt;do &lt;/span&gt;container&amp;gt; ash
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Agora veja que está dentro do container, pode verificar &lt;code&gt;cat /etc/os-release&lt;/code&gt; ou &lt;code&gt;env&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Também é possível executar um comando específico sem precisar abrir uma sessão interativa — por exemplo, para conferir uma variável de ambiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;nome ou ID &lt;span class="k"&gt;do &lt;/span&gt;container&amp;gt; &lt;span class="nb"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Desta forma você não precisará entrar no container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Parando e removendo containers
&lt;/h2&gt;

&lt;p&gt;Para parar um container em execução:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker stop &amp;lt;nome ou ID &lt;span class="k"&gt;do &lt;/span&gt;container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parar não remove o container — ele continua existindo (parado), até que você remova explicitamente ou tenha usado &lt;code&gt;--rm&lt;/code&gt; na criação. &lt;/p&gt;

&lt;p&gt;Para remover manualmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;nome ou ID &lt;span class="k"&gt;do &lt;/span&gt;container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Acompanhando logs
&lt;/h2&gt;

&lt;p&gt;Containers normalmente escrevem seus logs em &lt;code&gt;stdout&lt;/code&gt;/&lt;code&gt;stderr&lt;/code&gt;, e o Docker captura isso automaticamente. Para visualizar (e acompanhar em tempo real, como um &lt;code&gt;tail -f&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;nome ou ID &lt;span class="k"&gt;do &lt;/span&gt;container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sem a flag &lt;code&gt;-f&lt;/code&gt;, o comando apenas imprime os logs existentes até o momento, sem continuar acompanhando.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitorando recursos
&lt;/h2&gt;

&lt;p&gt;Para ver, em tempo real, o consumo de CPU, memória, I/O de disco e rede de todos os containers em execução:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker stats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comando é útil para identificar rapidamente containers consumindo recursos excessivos, sem precisar recorrer a ferramentas externas de monitoramento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Com os comandos essenciais da CLI em mãos, já é possível operar containers no dia a dia com confiança. Mas até aqui, os dados dentro dos containers são efêmeros — se o container for removido, os dados vão junto. Na &lt;strong&gt;Parte 3&lt;/strong&gt; desta série, vamos resolver isso com &lt;strong&gt;volumes&lt;/strong&gt;, garantindo persistência de dados entre execuções.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continua na Parte 3.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>Parte 1: Instalando o Docker no Debian</title>
      <dc:creator>Celso Nery</dc:creator>
      <pubDate>Tue, 18 Aug 2026 22:44:05 +0000</pubDate>
      <link>https://dev.to/celsonery/docker-para-desenvolvedores-j48</link>
      <guid>https://dev.to/celsonery/docker-para-desenvolvedores-j48</guid>
      <description>&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/celsonery/part-1-installing-on-debian-480h"&gt;English version here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Docker para Desenvolvedores - Parte 1: Instalando o Docker no Debian
&lt;/h1&gt;

&lt;p&gt;Antes de rodar qualquer container — seja para uma aplicação isolada, seja como pré-requisito para um cluster Kubernetes — é preciso ter o &lt;strong&gt;Docker Engine&lt;/strong&gt; instalado e configurado corretamente no servidor. Este artigo cobre a instalação completa no Debian, do zero até o primeiro container rodando.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use &lt;code&gt;sudo&lt;/code&gt; antes dos comandos abaixo caso esteja executando como usuário comum (não como root).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Atualizando o sistema
&lt;/h2&gt;

&lt;p&gt;Antes de instalar qualquer pacote novo, atualize a lista de pacotes e o sistema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt update&lt;/span&gt;
&lt;span class="c"&gt;# apt upgrade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instalando pacotes necessários
&lt;/h2&gt;

&lt;p&gt;Alguns pacotes são pré-requisitos para adicionar repositórios externos com segurança (chaves GPG, HTTPS, etc.):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt install curl gnupg2 apt-transport-https software-properties-common ca-certificates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adicionando o repositório do Docker
&lt;/h2&gt;

&lt;p&gt;Baixe e registre a chave GPG oficial do Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crie o arquivo de repositório em &lt;code&gt;/etc/apt/sources.list.d/docker.list&lt;/code&gt; e adicione este conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deb &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64 signed-by&lt;span class="o"&gt;=&lt;/span&gt;/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/debian bookworm stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Atenção à versão do Debian:&lt;/strong&gt; o nome (&lt;code&gt;bookworm&lt;/code&gt;, no exemplo) precisa corresponder à versão do seu Debian — &lt;code&gt;bookworm&lt;/code&gt; é o Debian 12, &lt;code&gt;bullseye&lt;/code&gt; é o Debian 11, &lt;code&gt;buster&lt;/code&gt; é o Debian 10. Para descobrir qual é o codinome da sua instalação, rode:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;

ou

&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/os-release
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;E substitua &lt;code&gt;bookworm&lt;/code&gt; pelo valor retornado, caso esteja usando uma versão diferente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Container runtime: Docker ou containerd?
&lt;/h2&gt;

&lt;p&gt;Se o objetivo final é montar um &lt;strong&gt;cluster Kubernetes&lt;/strong&gt;, vale uma pausa aqui: o Kubernetes não usa o Docker diretamente como runtime desde a versão 1.24 — ele depende do &lt;strong&gt;containerd&lt;/strong&gt; (que, inclusive, já vem junto com a instalação do Docker Engine, mas também pode ser instalado isoladamente). Se esse for o seu caso, siga direto para o artigo de &lt;a href="https://dev.to/celsonery/montando-um-cluster-kubernetes-on-premise-parte-2-instalando-containerd-e-kubernetes-ode"&gt;instalação do Kubernetes&lt;/a&gt;, que cobre a instalação do containerd especificamente para esse cenário.&lt;/p&gt;

&lt;p&gt;Se o objetivo é usar o &lt;strong&gt;Docker Engine completo&lt;/strong&gt; (para rodar containers isolados, Docker Compose, etc.), continue com os passos abaixo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando o Docker
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt update&lt;/span&gt;
&lt;span class="c"&gt;# apt install docker-ce&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Se você tiver problemas ao executar containers com a versão mais recente, é possível instalar uma versão anterior como a 18.06.0:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# apt install docker-ce=18.06.0~ce~3-0~debian&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Configurando o daemon
&lt;/h2&gt;

&lt;p&gt;Crie o arquivo &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; com as seguintes configurações:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exec-opts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"native.cgroupdriver=systemd"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"log-driver"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"json-file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"log-opts"&lt;/span&gt;&lt;span class="p"&gt;:&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;&lt;span class="nl"&gt;"max-size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100m"&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;&lt;span class="nl"&gt;"storage-driver"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"overlay2"&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;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa configuração:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usa o &lt;code&gt;systemd&lt;/code&gt; como cgroup driver (importante para manter consistência com outros serviços gerenciados por &lt;code&gt;systemd&lt;/code&gt; no sistema, incluindo o próprio Kubernetes, caso você venha a instalá-lo depois);&lt;/li&gt;
&lt;li&gt;Limita o tamanho dos logs de cada container a 100MB, evitando que containers "barulhentos" encham o disco com logs;&lt;/li&gt;
&lt;li&gt;Usa o driver de armazenamento &lt;code&gt;overlay2&lt;/code&gt;, recomendado atualmente para a maioria dos casos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crie o diretório de override do serviço systemd do Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# mkdir -p /etc/systemd/system/docker.service.d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recarregue e reinicie o serviço:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl daemon-reload
systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Permitindo uso do Docker por um usuário comum
&lt;/h2&gt;

&lt;p&gt;Por padrão, comandos do Docker exigem privilégios de root. Para permitir que um usuário comum rode containers sem precisar de &lt;code&gt;sudo&lt;/code&gt; em todo comando, adicione-o ao grupo &lt;code&gt;docker&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# usermod -aG docker $USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;É necessário fazer logout e login novamente (ou reiniciar a sessão) para que a mudança de grupo tenha efeito.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Verificando a instalação
&lt;/h2&gt;

&lt;p&gt;Confirme que o Docker está instalado e funcionando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saída deve ser parecida com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client:
 Version:           18.06.0-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        0ffa825
 Built:             Wed Jul 18 19:09:33 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.0-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       0ffa825
  Built:            Wed Jul 18 19:07:38 2018
  OS/Arch:          linux/amd64
  Experimental:     false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A versão exibida vai variar conforme a versão instalada no seu sistema — o exemplo acima reflete a versão 18.06.0.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Rodando o primeiro container
&lt;/h2&gt;

&lt;p&gt;O teste clássico, usando a imagem oficial de exemplo do Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou, para um teste um pouco mais tangível, subindo um servidor web Apache (httpd) na porta 80:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para confirmar que funcionou, acesse pelo navegador o IP da máquina host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se a página padrão do Apache aparecer, a instalação do Docker está completa e funcionando corretamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações finais
&lt;/h2&gt;

&lt;p&gt;Com o Docker instalado, configurado com o cgroup driver correto e testado com sucesso, o servidor já está pronto tanto para rodar containers isolados no dia a dia. Na &lt;strong&gt;Parte 2&lt;/strong&gt; desta série, iremos explorar os comandos mais comuns do Docker CLI: &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;logs&lt;/code&gt;, and &lt;code&gt;stats&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continua na Parte 2.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>debian</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
