<?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: Suleiman Dibirov</title>
    <description>The latest articles on DEV Community by Suleiman Dibirov (@idsulik).</description>
    <link>https://dev.to/idsulik</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F449085%2Ffa5858be-aefb-4453-baa6-ba2f9178fe5c.jpg</url>
      <title>DEV Community: Suleiman Dibirov</title>
      <link>https://dev.to/idsulik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/idsulik"/>
    <language>en</language>
    <item>
      <title>Docker Model Runner: Running AI Models Locally</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Sat, 12 Apr 2025 05:36:30 +0000</pubDate>
      <link>https://dev.to/idsulik/docker-model-runner-running-ai-models-locally-1a3n</link>
      <guid>https://dev.to/idsulik/docker-model-runner-running-ai-models-locally-1a3n</guid>
      <description>&lt;p&gt;Docker has released an interesting new feature in beta that should interest anyone working with generative AI. &lt;a href="https://docs.docker.com/desktop/features/model-runner/" rel="noopener noreferrer"&gt;Docker Model Runner&lt;/a&gt; allows you to load, run, and manage AI models directly on your local computer without the need to configure complex infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Docker Model Runner and why do you need it?
&lt;/h2&gt;

&lt;p&gt;Docker Model Runner is a plugin for Docker Desktop that significantly simplifies working with AI models. &lt;/p&gt;

&lt;p&gt;The feature is currently in beta testing, available in Docker Desktop version 4.40 and above, and is currently only supported on Macs with Apple Silicon processors.&lt;/p&gt;

&lt;p&gt;The plugin allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download models from Docker Hub (from the 'ai' namespace)&lt;/li&gt;
&lt;li&gt;Run AI models directly from the command line&lt;/li&gt;
&lt;li&gt;Manage local models (add, view, remove)&lt;/li&gt;
&lt;li&gt;Interact with models through specified prompts or in chat mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the key advantages of Docker Model Runner is the optimization of resource usage. Models are downloaded from Docker Hub only on first use and stored locally. They are loaded into memory only during query execution and unloaded when not in use. Since modern AI models can be quite large, the initial download may take some time, but they are then cached locally for quick access.&lt;/p&gt;

&lt;p&gt;Another important advantage is the support for OpenAI-compatible APIs, which significantly simplifies integration with existing applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Docker Model Runner Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Checking status
&lt;/h3&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 model status
Docker Model Runner is running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Viewing available commands
&lt;/h3&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 model &lt;span class="nb"&gt;help
&lt;/span&gt;Usage:  docker model COMMAND

Docker Model Runner

Commands:
  inspect     Display detailed information on one model
  list        List the available models that can be run with the Docker Model Runner
  pull        Download a model
  &lt;span class="nb"&gt;rm          &lt;/span&gt;Remove a model downloaded from Docker Hub
  run         Run a model with the Docker Model Runner
  status      Check &lt;span class="k"&gt;if &lt;/span&gt;the Docker Model Runner is running
  version     Show the Docker Model Runner version

Run &lt;span class="s1"&gt;'docker model COMMAND --help'&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information on a command.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Downloading a model
&lt;/h3&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 model pull ai/smollm2
Downloaded: 0.00 MB
Model ai/smollm2 pulled successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the download it shows the correct size, but after downloading it shows 0.00 MB, but as I mentioned above, this feature is still in beta testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Viewing local models
&lt;/h3&gt;

&lt;p&gt;Example output:&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 model list
MODEL       PARAMETERS  QUANTIZATION    ARCHITECTURE  MODEL ID      CREATED      SIZE
ai/smollm2  361.82 M    IQ2_XXS/Q4_K_M  llama         354bf30d0aa3  2 weeks ago  256.35 MiB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running a model
&lt;/h3&gt;

&lt;p&gt;With a one-time prompt:&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 model run ai/smollm2 &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In dialogue mode:&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 model run ai/smollm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Removing a model
&lt;/h3&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 model &lt;span class="nb"&gt;rm &lt;/span&gt;ai/smollm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Integrating Docker Model Runner into your applications
&lt;/h2&gt;

&lt;p&gt;Docker Model Runner provides OpenAI-compatible API endpoints, making it easy to integrate with existing applications. Here's an example of calling the chat/completions endpoint from a 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="c"&gt;#!/bin/sh&lt;/span&gt;

curl http://model-runner.docker.internal/engines/llama.cpp/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
        "model": "ai/smollm2",
        "messages": [
            {
                "role": "system",
                "content": "You are a helpful assistant."
            },
            {
                "role": "user",
                "content": "Write 500 words about the fall of Rome."
            }
        ]
    }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use Docker Model Runner from the host via the Docker socket:&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;#!/bin/sh&lt;/span&gt;

curl &lt;span class="nt"&gt;--unix-socket&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.docker/run/docker.sock &lt;span class="se"&gt;\&lt;/span&gt;
    localhost/exp/vDD4.40/engines/llama.cpp/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
        "model": "ai/smollm2",
        "messages": [
            {
                "role": "system",
                "content": "You are a helpful assistant."
            },
            {
                "role": "user",
                "content": "Write 500 words about the fall of Rome."
            }
        ]
    }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick start with a GenAI application example
&lt;/h2&gt;

&lt;p&gt;If you want to quickly try Docker Model Runner with a ready-made generative AI application, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the example repository:
&lt;/li&gt;
&lt;/ol&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;git clone https://github.com/docker/hello-genai.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In the terminal, navigate to the hello-genai directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run run.sh to download the selected model and launch the application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the application in your browser at the address specified in the repository's README.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Available API endpoints
&lt;/h2&gt;

&lt;p&gt;After enabling Docker Model Runner, the following APIs are available:&lt;/p&gt;

&lt;h4&gt;
  
  
  Inside containers
&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://model-runner.docker.internal/" rel="noopener noreferrer"&gt;http://model-runner.docker.internal/&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Model management
POST /models/create
GET /models
GET /models/{namespace}/{name}
DELETE /models/{namespace}/{name}

# OpenAI-compatible endpoints
GET /engines/llama.cpp/v1/models
GET /engines/llama.cpp/v1/models/{namespace}/{name}
POST /engines/llama.cpp/v1/chat/completions
POST /engines/llama.cpp/v1/completions
POST /engines/llama.cpp/v1/embeddings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: You can also omit llama.cpp.&lt;br&gt;
For example, POST /engines/v1/chat/completions.&lt;/p&gt;
&lt;h4&gt;
  
  
  Inside or outside containers (on the host)
&lt;/h4&gt;

&lt;p&gt;The same endpoints on /var/run/docker.sock&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# While the feature is in beta
With the prefix /exp/vDD4.40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Known issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The docker model command is not recognized
&lt;/h3&gt;

&lt;p&gt;If you get the error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker: 'model' is not a docker command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that Docker cannot find the plugin. Solution:&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;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /Applications/Docker.app/Contents/Resources/cli-plugins/docker-model ~/.docker/cli-plugins/docker-model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  No protection against running excessively large models
&lt;/h3&gt;

&lt;p&gt;Currently, Docker Model Runner does not include protection against running models that exceed available system resources. Attempting to run a model that is too large can lead to serious slowdowns or temporary system inoperability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Errors with failed downloads
&lt;/h3&gt;

&lt;p&gt;If the model download fails, the docker model run command may still launch the chat interface, although the model is actually unavailable. In this case, it is recommended to manually repeat the docker model pull command.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to enable or disable the feature
&lt;/h2&gt;

&lt;p&gt;Docker Model Runner is enabled by default in Docker Desktop. If you want to disable this feature:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Docker Desktop settings&lt;/li&gt;
&lt;li&gt;Go to the Beta tab in the Features in development section&lt;/li&gt;
&lt;li&gt;Uncheck Enable Docker Model Runner&lt;/li&gt;
&lt;li&gt;Click Apply &amp;amp; restart&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you don't see the Enable Docker Model Runner checkbox, then enable experimental features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker Model Runner provides a convenient way to work with AI models locally, which is especially useful for developers who want to experiment with generative AI without the need to connect to cloud APIs or configure complex infrastructure.&lt;/p&gt;

&lt;p&gt;The feature is in beta, so some issues may arise, but Docker is actively working on fixing them and accepts feedback through the Give feedback link next to the Enable Docker Model Runner setting.&lt;/p&gt;

&lt;p&gt;If you're working with generative AI or just want to try local models without unnecessary complications, Docker Model Runner is a great tool worth adding to your arsenal.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Sat, 07 Dec 2024 10:58:48 +0000</pubDate>
      <link>https://dev.to/idsulik/-34ic</link>
      <guid>https://dev.to/idsulik/-34ic</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/idsulik" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F449085%2Ffa5858be-aefb-4453-baa6-ba2f9178fe5c.jpg" alt="idsulik"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/idsulik/a-beginners-guide-to-docker-health-checks-and-container-monitoring-3kh6" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A Beginner's Guide to Docker Health Checks and Container Monitoring&lt;/h2&gt;
      &lt;h3&gt;Suleiman Dibirov ・ Dec 7&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>A Beginner's Guide to Docker Health Checks and Container Monitoring</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Sat, 07 Dec 2024 10:55:13 +0000</pubDate>
      <link>https://dev.to/idsulik/a-beginners-guide-to-docker-health-checks-and-container-monitoring-3kh6</link>
      <guid>https://dev.to/idsulik/a-beginners-guide-to-docker-health-checks-and-container-monitoring-3kh6</guid>
      <description>&lt;p&gt;Hey there! 👋 If you're new to Docker and wondering, "How do I know if my containers are running properly?", you're in the right place! Let's break down Docker health checks in a way that's easy to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Docker Health Check?
&lt;/h2&gt;

&lt;p&gt;Think of a health check as a way to ask your container, "Hey, are you feeling okay?" It's like a regular checkup at the doctor's office but for your containers! Docker will periodically run a command you specify to check if your application is working correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do You Need Health Checks? 🎯
&lt;/h2&gt;

&lt;p&gt;Imagine you're running a web application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your container might be running, but what if your app crashed inside it?&lt;/li&gt;
&lt;li&gt;What if your app is running but can't connect to its database?&lt;/li&gt;
&lt;li&gt;How would you know if something's wrong before your users do?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's where health checks come in! They help you catch these issues automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your First Health Check
&lt;/h2&gt;

&lt;p&gt;Let's start with a super simple example. Say you have a Node.js web application:&lt;br&gt;
&lt;/p&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; node:alpine&lt;/span&gt;

&lt;span class="c"&gt;# Install curl for health checks&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; curl

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Then copy the rest&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;HEALTHCHECK&lt;/span&gt;&lt;span class="s"&gt; --interval=30s --timeout=3s --retries=3 \&lt;/span&gt;
  CMD curl -f http://localhost:3000/health || exit 1

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down what this health check does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--interval=30s&lt;/code&gt;: Checks every 30 seconds&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--timeout=3s&lt;/code&gt;: Waits up to 3 seconds for a response&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--retries=3&lt;/code&gt;: Tries 3 times before marking as unhealthy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;curl -f http://localhost:3000/health&lt;/code&gt;: The actual check - tries to access your app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;|| exit 1&lt;/code&gt;: If the curl fails, the health check fails&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Checking Container Health Status
&lt;/h2&gt;

&lt;p&gt;After you've added a health check, you can see how your container is doing:&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;# Start your container&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; my-app my-node-app

&lt;span class="c"&gt;# Check its health status&lt;/span&gt;
docker ps

&lt;span class="c"&gt;# Get more detailed health info&lt;/span&gt;
docker inspect my-app | &lt;span class="nb"&gt;grep &lt;/span&gt;Health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see one of these states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;starting&lt;/code&gt;: Your container is starting up&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;healthy&lt;/code&gt;: Everything's good!&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unhealthy&lt;/code&gt;: Something's wrong&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Simple Health Check Endpoint
&lt;/h2&gt;

&lt;p&gt;For a web application, you'll want to add a health check endpoint. Here's a super simple example in Node.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Simple health check endpoint&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/health&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App listening at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update your Dockerfile to use this endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;HEALTHCHECK&lt;/span&gt;&lt;span class="s"&gt; --interval=30s --timeout=3s --retries=3 \&lt;/span&gt;
  CMD curl -f http://localhost:3000/health || exit 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Docker Compose? It's Easy!
&lt;/h2&gt;

&lt;p&gt;If you're using Docker Compose, you can add health checks like 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;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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&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;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -f http://localhost:3000/health || exit &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;start_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;40s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;start_period&lt;/code&gt; gives your app some time to start up before running health checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Monitoring for Beginners
&lt;/h2&gt;

&lt;p&gt;Want to see what your container is doing? Try these simple commands:&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;# See container resource usage&lt;/span&gt;
docker stats

&lt;span class="c"&gt;# View container logs&lt;/span&gt;
docker logs my-app

&lt;span class="c"&gt;# Follow logs in real-time&lt;/span&gt;
docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tips for Getting Started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start Simple&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Begin with basic HTTP checks&lt;/li&gt;
&lt;li&gt;Don't overcomplicate your health checks at first&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test Your Health Checks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try stopping your application inside the container&lt;/li&gt;
&lt;li&gt;Make sure the health check detects the problem&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Common Gotchas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure curl is installed in your container&lt;/li&gt;
&lt;li&gt;Give your app enough time to start up&lt;/li&gt;
&lt;li&gt;Check the right port (container port, not host port)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Health checks don't have to be complicated! Start with these basics, and you'll be on your way to more reliable Docker containers. Remember, even a simple health check is better than no health check at all.&lt;/p&gt;

&lt;p&gt;Happy Dockering! 🐳&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found this helpful? Follow me for more Docker tips and tricks! And don't forget to leave a ❤️ if you enjoyed this article.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Beginner's Guide to Docker Compose for Developers</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Sun, 01 Dec 2024 10:08:56 +0000</pubDate>
      <link>https://dev.to/idsulik/a-beginners-guide-to-docker-compose-for-developers-55dm</link>
      <guid>https://dev.to/idsulik/a-beginners-guide-to-docker-compose-for-developers-55dm</guid>
      <description>&lt;p&gt;If you're a developer who's been using Docker containers but finding yourself typing long &lt;code&gt;docker run&lt;/code&gt; commands or managing multiple containers manually, it's time to level up your workflow with Docker Compose. This guide will walk you through the basics of Docker Compose and show you how to simplify your development environment setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Docker Compose?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt; is a tool that helps you define and share multi-container applications. With Compose, you use a YAML file to configure your application's &lt;code&gt;services&lt;/code&gt;, &lt;code&gt;networks&lt;/code&gt;, and &lt;code&gt;volumes&lt;/code&gt;. Then, with a single command, you create and start all the services from your configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should You Use Docker Compose?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Configuration&lt;/strong&gt;: Define your entire application stack in a single file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducible Environments&lt;/strong&gt;: Share your application setup with other developers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy Testing&lt;/strong&gt;: Create isolated testing environments quickly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control&lt;/strong&gt;: Track changes to your application environment alongside your code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;First, ensure you have both &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker and Docker Compose installed&lt;/a&gt;. Docker Desktop for Windows and Mac comes with Compose, but Linux users might need to install it separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  The compose.yml File
&lt;/h3&gt;

&lt;p&gt;The heart of Docker Compose is the &lt;code&gt;compose.yml&lt;/code&gt; file (or &lt;code&gt;docker-compose.yml&lt;/code&gt; for backward compatibility). Here's a simple example:&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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&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;3000:3000"&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;.:/app&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NODE_ENV=development&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;postgres:13&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=myuser&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=mypassword&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;postgres_data:/var/lib/postgresql/data&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;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down each configuration element:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;services&lt;/code&gt;: The top-level key that defines all your application's containers/services&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each indented key under &lt;code&gt;services&lt;/code&gt; (like &lt;code&gt;web&lt;/code&gt; and &lt;code&gt;db&lt;/code&gt;) is a service name you choose&lt;/li&gt;
&lt;li&gt;Service names are used for network aliases and container prefixes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;build&lt;/code&gt;: Specifies the build configuration for creating a container image&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt; means build from Dockerfile in the current directory&lt;/li&gt;
&lt;li&gt;Can also specify a path to a directory containing a Dockerfile&lt;/li&gt;
&lt;li&gt;Can be expanded to include build context and arguments:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./dir&lt;/span&gt;
   &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile.dev&lt;/span&gt;
   &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;development&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ports&lt;/code&gt;: Maps container ports to host ports&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Format is &lt;code&gt;"HOST_PORT:CONTAINER_PORT"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;"3000:3000"&lt;/code&gt; maps container port 3000 to host port 3000&lt;/li&gt;
&lt;li&gt;Can specify multiple port mappings&lt;/li&gt;
&lt;li&gt;Can use port ranges: &lt;code&gt;"3000-3005:3000-3005"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;volumes&lt;/code&gt;: Defines mounted volumes for data persistence and file sharing&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bind mounts: &lt;code&gt;./host/path:/container/path&lt;/code&gt; maps a host directory to container&lt;/li&gt;
&lt;li&gt;Named volumes: &lt;code&gt;volume_name:/container/path&lt;/code&gt; uses a Docker-managed volume&lt;/li&gt;
&lt;li&gt;Anonymous volumes: &lt;code&gt;/container/path&lt;/code&gt; creates an unnamed Docker-managed volume&lt;/li&gt;
&lt;li&gt;Can specify read-only volumes: &lt;code&gt;./host/path:/container/path:ro&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;environment&lt;/code&gt;: Sets environment variables inside the container&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be a list: &lt;code&gt;- KEY=value&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Or a map:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;development&lt;/span&gt;
   &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;image&lt;/code&gt;: Specifies a pre-built Docker image to use&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be from Docker Hub: &lt;code&gt;postgres:13&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Or private registry: &lt;code&gt;registry.example.com/image:tag&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Used when you don't need to build an image locally&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Named volumes declaration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The top-level &lt;code&gt;volumes&lt;/code&gt; key declares named volumes used in services&lt;/li&gt;
&lt;li&gt;These volumes persist even when containers are removed&lt;/li&gt;
&lt;li&gt;Can specify volume drivers and options:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
     &lt;span class="na"&gt;driver_opts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;none&lt;/span&gt;
       &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/path/on/host&lt;/span&gt;
       &lt;span class="na"&gt;o&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bind&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Common additional configurations you might need:&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="c1"&gt;# Restart policy&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;  &lt;span class="c1"&gt;# or 'no', 'on-failure', 'unless-stopped'&lt;/span&gt;

    &lt;span class="c1"&gt;# Dependencies&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="c1"&gt;# Custom container name&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp_web&lt;/span&gt;

    &lt;span class="c1"&gt;# Additional hosts entries&lt;/span&gt;
    &lt;span class="na"&gt;extra_hosts&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;host.docker.internal:host-gateway"&lt;/span&gt;

    &lt;span class="c1"&gt;# Resource limits&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;cpus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.5'&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;512M&lt;/span&gt;

    &lt;span class="c1"&gt;# Health check&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&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;CMD"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;curl"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-f"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3000"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These configurations allow you to define complex, multi-container applications in a declarative way. The compose file serves as both documentation and executable configuration, making it easier to share and maintain your application's infrastructure requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essential Commands
&lt;/h2&gt;

&lt;p&gt;Here are the Docker Compose commands you'll use frequently:&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;# Start your services&lt;/span&gt;
docker compose up

&lt;span class="c"&gt;# Run in detached mode&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;

&lt;span class="c"&gt;# Stop services (keeps containers)&lt;/span&gt;
docker compose stop

&lt;span class="c"&gt;# Stop and remove containers, networks&lt;/span&gt;
docker compose down

&lt;span class="c"&gt;# Stop and remove containers, networks, volumes&lt;/span&gt;
docker compose down &lt;span class="nt"&gt;-v&lt;/span&gt;

&lt;span class="c"&gt;# View logs&lt;/span&gt;
docker compose logs

&lt;span class="c"&gt;# View logs for specific service&lt;/span&gt;
docker compose logs service_name

&lt;span class="c"&gt;# Follow logs&lt;/span&gt;
docker compose logs &lt;span class="nt"&gt;-f&lt;/span&gt;

&lt;span class="c"&gt;# Rebuild services&lt;/span&gt;
docker compose build

&lt;span class="c"&gt;# Execute command in a running container&lt;/span&gt;
docker compose &lt;span class="nb"&gt;exec &lt;/span&gt;service_name &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;span class="c"&gt;# Example: docker compose exec web npm test&lt;/span&gt;

&lt;span class="c"&gt;# Run a one-off command&lt;/span&gt;
docker compose run &lt;span class="nt"&gt;--rm&lt;/span&gt; service_name &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;span class="c"&gt;# Example: docker compose run --rm web npm install&lt;/span&gt;

&lt;span class="c"&gt;# List running containers&lt;/span&gt;
docker compose ps

&lt;span class="c"&gt;# Check service status&lt;/span&gt;
docker compose top

&lt;span class="c"&gt;# Pull latest images&lt;/span&gt;
docker compose pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Example: MERN Stack
&lt;/h2&gt;

&lt;p&gt;Let's look at a practical example using a MERN (MongoDB, Express, React, Node.js) stack:&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;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./frontend&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&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;3000:3000"&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;./frontend:/app&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/app/node_modules&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;REACT_APP_API_URL=http://localhost:5000&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;backend&lt;/span&gt;

  &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./backend&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&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;5000:5000"&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;./backend:/app&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/app/node_modules&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MONGODB_URI=mongodb://mongodb:27017/myapp&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;mongodb&lt;/span&gt;

  &lt;span class="na"&gt;mongodb&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;mongo: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;27017:27017"&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;mongodb_data:/data/db&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;mongodb_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use Version Control&lt;/strong&gt;: Always include your compose file in version control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment Variables&lt;/strong&gt;: Use &lt;code&gt;.env&lt;/code&gt; files for sensitive data:
&lt;/li&gt;
&lt;/ol&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;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Named Volumes&lt;/strong&gt;: Use named volumes instead of bind mounts for databases:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;mongodb_data:/data/db&lt;/span&gt;  &lt;span class="c1"&gt;# Good&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./data:/data/db&lt;/span&gt;       &lt;span class="c1"&gt;# Not recommended for databases&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies&lt;/strong&gt;: Use &lt;code&gt;depends_on&lt;/code&gt; to manage service startup order:
&lt;/li&gt;
&lt;/ol&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Port Conflicts
&lt;/h3&gt;

&lt;p&gt;If you see "port is already allocated" errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check for running containers using the same ports&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;docker compose ps&lt;/code&gt; to list running containers&lt;/li&gt;
&lt;li&gt;Change the port mapping in your compose file&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Volume Permissions
&lt;/h3&gt;

&lt;p&gt;If you encounter permission issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure proper ownership of mounted volumes&lt;/li&gt;
&lt;li&gt;Consider using &lt;code&gt;user&lt;/code&gt; directive in your service definition:
&lt;/li&gt;
&lt;/ul&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;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1000:1000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker Compose is an invaluable tool for modern development workflows. It simplifies container management, makes development environments reproducible, and helps teams work more efficiently. Start with simple configurations and gradually add more features as your needs grow.&lt;/p&gt;

&lt;p&gt;Remember: the goal is to make development easier, not more complicated. Don't over-engineer your Compose files – keep them simple and focused on your immediate needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Happy containerizing! 🐳
&lt;/h2&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introducing Helm CEL: A More Expressive Way to Validate Your Helm Charts</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Sun, 17 Nov 2024 05:36:26 +0000</pubDate>
      <link>https://dev.to/idsulik/introducing-helm-cel-a-more-expressive-way-to-validate-your-helm-charts-2kcb</link>
      <guid>https://dev.to/idsulik/introducing-helm-cel-a-more-expressive-way-to-validate-your-helm-charts-2kcb</guid>
      <description>&lt;p&gt;If you've worked with Helm charts, you're probably familiar with the challenge of validating &lt;code&gt;values.yaml&lt;/code&gt;. While Helm's built-in JSON Schema validation works, it can be cumbersome and limiting. Today, I want to introduce you to &lt;a href="https://github.com/idsulik/helm-cel" rel="noopener noreferrer"&gt;Helm CEL&lt;/a&gt;, a plugin that brings the power of Google's Common Expression Language (&lt;a href="https://cel.dev/" rel="noopener noreferrer"&gt;CEL&lt;/a&gt;) to Helm chart validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CEL?
&lt;/h2&gt;

&lt;p&gt;Before diving in, let's quickly cover what CEL is. Common Expression Language (CEL) is a simple expression language created by Google that lets you write concise, powerful validation rules. It's used in Kubernetes CRD validation, Istio configuration, and many other projects in the cloud-native ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use CEL Instead of JSON Schema?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;More Expressive&lt;/strong&gt;: CEL allows you to write complex validation rules in a more natural and readable way&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Familiar Syntax&lt;/strong&gt;: If you're coming from programming languages like Python or JavaScript, CEL's syntax will feel natural&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-Safe&lt;/strong&gt;: CEL provides strong type checking while remaining flexible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built for Cloud Native&lt;/strong&gt;: CEL is already used throughout the Kubernetes ecosystem&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;First, install the plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm plugin &lt;span class="nb"&gt;install &lt;/span&gt;https://github.com/idsulik/helm-cel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of creating a &lt;code&gt;values.schema.json&lt;/code&gt;, you'll create a &lt;code&gt;values.cel.yaml&lt;/code&gt; file in your chart directory. Here's a simple example:&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;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;has(values.service)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has(values.service.port)"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;required"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;values.service.port&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;values.service.port&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;65535"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;must&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;be&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;between&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;65535"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!(has(values.replicaCount))&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;values.replicaCount&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;if&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;replicaCount&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;set,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;it&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;must&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;be&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;at&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;least&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To validate your chart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm cel ./mychart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Examples
&lt;/h2&gt;

&lt;p&gt;Let's look at some common validation patterns and how they're expressed in both JSON Schema and CEL.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Required Fields
&lt;/h3&gt;

&lt;p&gt;JSON Schema:&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;"required"&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;"service"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&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;"service"&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;"required"&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;"port"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"properties"&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;"port"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&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="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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CEL:&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;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;has(values.service)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has(values.service.port)"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;required"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Conditional Requirements
&lt;/h3&gt;

&lt;p&gt;JSON Schema:&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;"if"&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;"properties"&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;"persistence"&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;"const"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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="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;"then"&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;"required"&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;"storageClass"&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="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;CEL:&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;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!has(values.persistence)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;!values.persistence&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has(values.storageClass)"&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;storageClass&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;when&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;persistence&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;enabled"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Complex Validations
&lt;/h3&gt;

&lt;p&gt;JSON Schema can become quite verbose for complex validations. Here's a CEL example that would be much more complicated in JSON Schema:&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;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;!has(values.resources) || &lt;/span&gt;
      &lt;span class="s"&gt;(!has(values.resources.limits) &amp;amp;&amp;amp; !has(values.resources.requests)) ||&lt;/span&gt;
      &lt;span class="s"&gt;(has(values.resources.limits.memory) &amp;amp;&amp;amp; has(values.resources.requests.memory) &amp;amp;&amp;amp;&lt;/span&gt;
       &lt;span class="s"&gt;int(values.resources.requests.memory) &amp;lt;= int(values.resources.limits.memory))&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;resources&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;are&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;specified,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;request&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;must&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exceed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;limit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error Messages That Make Sense
&lt;/h2&gt;

&lt;p&gt;One of the best features of Helm CEL is its clear error messages. When validation fails, you get helpful output like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ Validation failed: replica count must be at least 1
   Rule: values.replicaCount &amp;gt;= 1
   Path: replicaCount
   Current value: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;CEL expressions are compiled and evaluated efficiently. The plugin adds minimal overhead to your Helm workflow, making it suitable for both development and CI/CD pipelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install the plugin: &lt;code&gt;helm plugin install https://github.com/idsulik/helm-cel&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/idsulik/helm-cel" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; for more examples&lt;/li&gt;
&lt;li&gt;Start writing your own validation rules!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/idsulik/helm-cel" rel="noopener noreferrer"&gt;Helm CEL&lt;/a&gt; brings a more expressive and maintainable way to validate your Helm charts. If you've ever found yourself fighting with JSON Schema or wanting more flexible validation rules, give it a try. The combination of familiar syntax, powerful expressions, and clear error messages makes it a valuable addition to any Helm user's toolkit.&lt;/p&gt;

&lt;p&gt;What validation patterns would you like to see? Let me know in the comments below!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>helm</category>
      <category>go</category>
    </item>
    <item>
      <title>Docker ARG vs ENV: Understanding Build-time and Runtime Variables</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Wed, 13 Nov 2024 15:57:39 +0000</pubDate>
      <link>https://dev.to/idsulik/docker-arg-vs-env-understanding-build-time-and-runtime-variables-473c</link>
      <guid>https://dev.to/idsulik/docker-arg-vs-env-understanding-build-time-and-runtime-variables-473c</guid>
      <description>&lt;p&gt;Are you confused about when to use &lt;code&gt;ARG&lt;/code&gt; versus &lt;code&gt;ENV&lt;/code&gt; in your Dockerfiles? You're not alone! This comprehensive guide will help you understand the key differences, use cases, and best practices for both build arguments (&lt;code&gt;ARG&lt;/code&gt;) and environment variables (&lt;code&gt;ENV&lt;/code&gt;) in Docker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;ARG&lt;/th&gt;
&lt;th&gt;ENV&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Available during build&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Available in running container&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be set in Dockerfile&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be overridden at build time&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persists in final image&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be used in FROM instruction&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Differences
&lt;/h2&gt;

&lt;p&gt;The fundamental difference between &lt;code&gt;ARG&lt;/code&gt; and &lt;code&gt;ENV&lt;/code&gt; lies in their scope and persistence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ARG&lt;/strong&gt; is only available during the build process&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ENV&lt;/strong&gt; sets environment variables that persist in the running container&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding ARG
&lt;/h2&gt;

&lt;p&gt;Build arguments (ARG) are variables that you can pass to Docker during the image build process using the &lt;code&gt;--build-arg&lt;/code&gt; flag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic ARG Syntax
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Declare the argument&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VERSION=latest&lt;/span&gt;

&lt;span class="c"&gt;# Use the argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:${VERSION}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20.04 &lt;span class="nt"&gt;-t&lt;/span&gt; my-ubuntu &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ARG Scoping Rules
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;ARGs declared before &lt;code&gt;FROM&lt;/code&gt; are only available during &lt;code&gt;FROM&lt;/code&gt; instruction&lt;/li&gt;
&lt;li&gt;To use &lt;code&gt;ARG&lt;/code&gt; after &lt;code&gt;FROM&lt;/code&gt;, you need to redeclare it&lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;FROM&lt;/code&gt; instruction clears all ARGs declared before it
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Global ARG&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BASE_IMAGE=ubuntu&lt;/span&gt;

&lt;span class="c"&gt;# Available in FROM&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ${BASE_IMAGE}:latest&lt;/span&gt;

&lt;span class="c"&gt;# Need to redeclare to use after FROM&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BASE_IMAGE&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Building from &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_IMAGE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Understanding ENV
&lt;/h2&gt;

&lt;p&gt;Environment variables (&lt;code&gt;ENV&lt;/code&gt;) are set in your image and are available both during build and when the container runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic ENV Syntax
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set a single environment variable&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; APP_VERSION=1.0.0&lt;/span&gt;

&lt;span class="c"&gt;# Set multiple environment variables&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production \&lt;/span&gt;
    PORT=3000 \
    APP_HOME=/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ENV Persistence
&lt;/h3&gt;

&lt;p&gt;ENVs persist across build stages and in the final container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1: Build&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Building in &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NODE_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Stage 2: Runtime&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:16-slim&lt;/span&gt;
&lt;span class="c"&gt;# NODE_ENV needs to be redefined if needed in this stage&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Building Different Versions of an Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build argument for version control&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; NODE_VERSION=16&lt;/span&gt;

&lt;span class="c"&gt;# Base image with specified version&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:${NODE_VERSION}&lt;/span&gt;

&lt;span class="c"&gt;# Environment variable for runtime configuration&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;

&lt;span class="c"&gt;# Redeclare ARG if needed after FROM&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; NODE_VERSION&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Node.js version: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NODE_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Application setup&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Runtime configuration&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT=3000 \&lt;/span&gt;
    APP_NAME=my-awesome-app

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Configurable Build Process
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build-time configuration&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; INSTALL_DEV_DEPS=false&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; ENABLE_TESTING=false&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:16&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Redeclare ARGs after FROM&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; INSTALL_DEV_DEPS&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; ENABLE_TESTING&lt;/span&gt;

&lt;span class="c"&gt;# Conditional installation of dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INSTALL_DEV_DEPS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;        npm &lt;span class="nb"&gt;install&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;        npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--production&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Conditional testing&lt;/span&gt;
&lt;span class="k"&gt;RUN if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ENABLE_TESTING&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;        npm &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Runtime configuration&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production \&lt;/span&gt;
    LOG_LEVEL=info

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use ARG for Build Flexibility&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version numbers&lt;/li&gt;
&lt;li&gt;Base image selection&lt;/li&gt;
&lt;li&gt;Build-time configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use ENV for Runtime Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application settings&lt;/li&gt;
&lt;li&gt;Service endpoints&lt;/li&gt;
&lt;li&gt;Feature flags&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Default Values&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;   &lt;span class="c"&gt;# Provide sensible defaults for ARGs&lt;/span&gt;
   ARG VERSION=latest
   ARG NODE_ENV=production

   &lt;span class="c"&gt;# ENVs should also have defaults&lt;/span&gt;
   ENV PORT=3000 \
       LOG_LEVEL=info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;   &lt;span class="c"&gt;# Document your build arguments&lt;/span&gt;
   &lt;span class="c"&gt;# Required: VERSION - Specify the application version to build&lt;/span&gt;
   &lt;span class="c"&gt;# Optional: NODE_ENV - Build environment (default: production)&lt;/span&gt;
   ARG VERSION
   ARG NODE_ENV=production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Security Considerations&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Never use ARG or ENV for secrets&lt;/li&gt;
&lt;li&gt;Use Docker secrets or environment files for sensitive data&lt;/li&gt;
&lt;li&gt;Remember that ENVs are visible in the image history&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ARG Scope Confusion&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Won't work as expected&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VERSION&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:${VERSION}&lt;/span&gt;

&lt;span class="c"&gt;# Need to redeclare&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VERSION&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build-time vs Runtime Values&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Wrong: Using ARG for runtime configuration&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; API_URL=http://api.example.com&lt;/span&gt;

&lt;span class="c"&gt;# Correct: Use ENV for runtime configuration&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; API_URL=http://api.example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Missing Defaults&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Risky: No default value&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VERSION&lt;/span&gt;

&lt;span class="c"&gt;# Better: Include a default&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VERSION=latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Combining ARG and ENV
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build argument with default&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;

&lt;span class="c"&gt;# Set ENV based on ARG&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=${NODE_ENV}&lt;/span&gt;

&lt;span class="c"&gt;# Now NODE_ENV persists in the container&lt;/span&gt;
&lt;span class="c"&gt;# but can be configured at build time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Multiple Build Stages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUILD_MODE=production&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=${BUILD_MODE}&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build

&lt;span class="c"&gt;# Production stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:16-slim&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUILD_MODE=production&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=${BUILD_MODE}&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/dist ./dist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using Docker Compose
&lt;/h3&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;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NODE_VERSION=16&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BUILD_MODE=development&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NODE_ENV=development&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PORT=3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Understanding the difference between &lt;code&gt;ARG&lt;/code&gt; and &lt;code&gt;ENV&lt;/code&gt; is crucial for building flexible and maintainable Docker images. Use &lt;code&gt;ARG&lt;/code&gt; for build-time configuration and &lt;code&gt;ENV&lt;/code&gt; for runtime settings. Remember that &lt;strong&gt;ARGs are only available during build&lt;/strong&gt;, while &lt;strong&gt;ENVs persist in the running container&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By following these guidelines and best practices, you can create more maintainable and configurable Docker images while avoiding common pitfalls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#arg" rel="noopener noreferrer"&gt;Docker ARG documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#env" rel="noopener noreferrer"&gt;Docker ENV documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/reference/commandline/build/" rel="noopener noreferrer"&gt;Docker build reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>development</category>
      <category>container</category>
    </item>
    <item>
      <title>Docker CLI Tricks Every Developer Should Know</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Sat, 02 Nov 2024 06:30:00 +0000</pubDate>
      <link>https://dev.to/idsulik/docker-cli-tricks-every-developer-should-know-fpl</link>
      <guid>https://dev.to/idsulik/docker-cli-tricks-every-developer-should-know-fpl</guid>
      <description>&lt;p&gt;The Docker CLI offers powerful commands that can significantly improve productivity, simplify workflows, and make managing containers more efficient. Here are some essential tricks and tips that every developer should know.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Inspecting Containers with &lt;code&gt;docker inspect&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#modern Docker client syntax&lt;/span&gt;
docker inspect &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'&lt;/span&gt;

&lt;span class="c"&gt;#old Docker client syntax&lt;/span&gt;
docker inspect &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{{.NetworkSettings.IPAddress}}'&lt;/span&gt; &amp;lt;container_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; Use &lt;code&gt;docker inspect&lt;/code&gt; to access detailed information about containers, images, and volumes, including IP addresses and mounted volumes. Use &lt;code&gt;--format&lt;/code&gt; with &lt;code&gt;docker inspect&lt;/code&gt; to extract specific fields:&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Cleaning Up Unused Resources Quickly&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker system prune

#output example
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; Over time, unused containers, images, and volumes accumulate and take up disk space. &lt;code&gt;docker system prune&lt;/code&gt; removes everything unused, or use &lt;code&gt;docker image prune&lt;/code&gt;, &lt;code&gt;docker container prune&lt;/code&gt;, and &lt;code&gt;docker volume prune&lt;/code&gt; for selective cleanup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Running One-Off Commands in Containers&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Execute one-off commands within a running container without starting a new one, using &lt;code&gt;docker exec&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; my_container /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Useful for debugging and checking runtime configurations inside containers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Limiting Resource Usage on Containers&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#command&lt;/span&gt;
docker run &lt;span class="nt"&gt;--memory&lt;/span&gt; &amp;lt;memory_limit&amp;gt; &lt;span class="nt"&gt;--cpus&lt;/span&gt; &amp;lt;cpu_limit&amp;gt;

&lt;span class="c"&gt;#example&lt;/span&gt;
docker run &lt;span class="nt"&gt;--memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;512m &lt;span class="nt"&gt;--cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 my_image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; Prevent resource hogging by limiting memory and CPU usage for each container. This ensures fair resource allocation:&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Checking Container Logs in Real-Time&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; The &lt;code&gt;-f&lt;/code&gt; option shows real-time log output, useful for debugging running services. For instance:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; my_container
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can also add &lt;code&gt;--tail&lt;/code&gt; to view only the most recent lines:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;--tail&lt;/span&gt; 50 my_container
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Exporting and Importing Images&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#export&lt;/span&gt;
docker save &lt;span class="nt"&gt;-o&lt;/span&gt; &amp;lt;filename.tar&amp;gt; &amp;lt;image_name&amp;gt;

&lt;span class="c"&gt;#import&lt;/span&gt;
docker load &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;filename.tar&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; Export and import images between machines without re-downloading them. Ideal for offline setups or environments with network restrictions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. &lt;strong&gt;Checking Running Container Stats&lt;/strong&gt;
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; Use &lt;code&gt;docker stats&lt;/code&gt; to monitor real-time metrics for CPU, memory, and network usage. It helps diagnose performance issues and visualize resource utilization for each container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. &lt;strong&gt;Binding Ports Dynamically&lt;/strong&gt;
&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;-P&lt;/span&gt; &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; With &lt;code&gt;-P&lt;/code&gt;, Docker maps exposed container ports to random available host ports. To see mapped ports, use:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; docker port &amp;lt;container_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alternatively, specify specific host ports using &lt;code&gt;-p&lt;/code&gt; (e.g., &lt;code&gt;docker run -p 8080:80 my_image&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. &lt;strong&gt;Quickly Build and Run Containers with &lt;code&gt;docker-compose&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; For multi-container applications, &lt;code&gt;docker-compose&lt;/code&gt; simplifies setup. The &lt;code&gt;-d&lt;/code&gt; flag runs services in the background, and &lt;code&gt;docker-compose up&lt;/code&gt; recreates only modified containers, speeding up development.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10. &lt;strong&gt;Viewing Disk Usage with &lt;code&gt;docker system df&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



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

&lt;span class="c"&gt;#output example&lt;/span&gt;
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              11                  6                   2.866GB             1.171GB &lt;span class="o"&gt;(&lt;/span&gt;40%&lt;span class="o"&gt;)&lt;/span&gt;
Containers          17                  13                  3.4MB               2.145MB &lt;span class="o"&gt;(&lt;/span&gt;63%&lt;span class="o"&gt;)&lt;/span&gt;
Local Volumes       9                   5                   849.5MB             315.1MB &lt;span class="o"&gt;(&lt;/span&gt;37%&lt;span class="o"&gt;)&lt;/span&gt;
Build Cache         0                   0                   0B                  0B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; See how much disk space Docker resources (images, containers, volumes) occupy. This command provides an overview of storage use, which is helpful for resource management.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Mastering these Docker CLI tricks can make a noticeable difference in your workflow, from managing resources efficiently to quickly debugging applications.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>container</category>
      <category>containers</category>
      <category>development</category>
    </item>
    <item>
      <title>Managing Container Lifecycles with Docker Compose Lifecycle Hooks</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Fri, 01 Nov 2024 10:05:08 +0000</pubDate>
      <link>https://dev.to/idsulik/managing-container-lifecycles-with-docker-compose-lifecycle-hooks-mjg</link>
      <guid>https://dev.to/idsulik/managing-container-lifecycles-with-docker-compose-lifecycle-hooks-mjg</guid>
      <description>&lt;p&gt;Docker Compose &lt;a href="https://github.com/docker/compose/releases/tag/v2.30.0" rel="noopener noreferrer"&gt;v2.30.0&lt;/a&gt; has introduced lifecycle hooks, making it easier to manage actions tied to container &lt;strong&gt;start&lt;/strong&gt; and &lt;strong&gt;stop&lt;/strong&gt; events. This feature lets developers handle key tasks more flexibly while keeping applications clean and secure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/compose/how-tos/lifecycle/" rel="noopener noreferrer"&gt;Lifecycle hooks in Docker Compose&lt;/a&gt; provide a powerful way to execute commands at specific points in a container's lifecycle. Features like &lt;strong&gt;post-start&lt;/strong&gt; and &lt;strong&gt;pre-stop&lt;/strong&gt; hooks can handle privileged tasks (like changing file permissions) without running the entire container with elevated permissions. Let's explore how these hooks work and how they can benefit your containerized applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Lifecycle Hooks in Docker Compose?
&lt;/h2&gt;

&lt;p&gt;Traditionally, Docker Compose manages a container's lifecycle through the &lt;code&gt;ENTRYPOINT&lt;/code&gt; and &lt;code&gt;COMMAND&lt;/code&gt; options. While effective, these fields can make managing start and stop tasks less flexible, especially if you need different tasks to execute at different points.&lt;/p&gt;

&lt;p&gt;Lifecycle hooks allow for tasks that require higher privileges (such as a root user) to be isolated from the main application logic. They let you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle privileged actions without compromising container security&lt;/li&gt;
&lt;li&gt;Streamline processes like file permissions, cleanup scripts, or backup routines&lt;/li&gt;
&lt;li&gt;Avoid bloating &lt;code&gt;ENTRYPOINT&lt;/code&gt; or &lt;code&gt;COMMAND&lt;/code&gt; with logic that's only needed on start or stop&lt;/li&gt;
&lt;li&gt;Execute multiple tasks in a defined order during container startup or shutdown&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Post-Start Hooks: Running Tasks After the Container Starts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Is a Post-Start Hook?
&lt;/h3&gt;

&lt;p&gt;A &lt;a href="https://docs.docker.com/compose/how-tos/lifecycle/#post-start-hooks" rel="noopener noreferrer"&gt;post-start hook&lt;/a&gt; is a command that runs after the container starts. These hooks are useful for tasks that need to be done right after the container is up and running but are not dependent on precise timing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execution Environment&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hooks run within the context of the running container&lt;/li&gt;
&lt;li&gt;They have access to the container's environment variables&lt;/li&gt;
&lt;li&gt;They can interact with the container's filesystem and services&lt;/li&gt;
&lt;li&gt;Multiple hooks execute in the order they are defined&lt;/li&gt;
&lt;li&gt;Each hook must complete before the next one starts&lt;/li&gt;
&lt;li&gt;If any hook fails, subsequent hooks are not executed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: Changing Volume Ownership with a Post-Start Hook
&lt;/h3&gt;

&lt;p&gt;When Docker volumes are created, they are assigned root ownership by default. If you need a non-root user to access volume files, a post-start hook can change the file ownership accordingly.&lt;/p&gt;

&lt;p&gt;Here's a complete &lt;code&gt;docker-compose.yml&lt;/code&gt; file that uses post-start hooks to set up proper volume permissions:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&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;backend&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1001&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;data:/data&lt;/span&gt;    
    &lt;span class="na"&gt;post_start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;chown"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-R"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1001:1001"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;chmod"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-R"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;755"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&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;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How It Works&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Volume Initialization&lt;/strong&gt;: Docker creates the &lt;code&gt;data&lt;/code&gt; volume with &lt;code&gt;root&lt;/code&gt; ownership&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Starts&lt;/strong&gt;: The container runs with &lt;code&gt;user: 1001&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission Setup&lt;/strong&gt;: Two post-start hooks execute sequentially:

&lt;ul&gt;
&lt;li&gt;First hook changes ownership to user 1001&lt;/li&gt;
&lt;li&gt;Second hook sets appropriate read/write permissions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Runs&lt;/strong&gt;: The application can now access the volume with proper permissions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note on Permissions&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;By specifying &lt;code&gt;user: root&lt;/code&gt; in the post-start hooks, the commands run with root privileges within the container. This allows the hooks to perform necessary privileged actions without granting root permissions to the main container process, enhancing security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-Stop Hooks: Executing Commands Before the Container Stops
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Is a Pre-Stop Hook?
&lt;/h3&gt;

&lt;p&gt;A &lt;a href="https://docs.docker.com/compose/how-tos/lifecycle/#pre-stop-hooks" rel="noopener noreferrer"&gt;pre-stop hook&lt;/a&gt; is a command that runs inside the container before Docker stops it. These hooks are invaluable for executing cleanup or backup tasks, ensuring data consistency before shutdown.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execution Environment&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hooks execute inside the running container&lt;/li&gt;
&lt;li&gt;They have access to the container's full environment&lt;/li&gt;
&lt;li&gt;They run only during graceful shutdowns (not during force stops)&lt;/li&gt;
&lt;li&gt;Multiple hooks execute in sequence&lt;/li&gt;
&lt;li&gt;Each hook must complete before proceeding to the next&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: Running a Cleanup Script with a Pre-Stop Hook
&lt;/h3&gt;

&lt;p&gt;Here's an example showing how to implement pre-stop hooks for proper application shutdown:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&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;backend&lt;/span&gt;
    &lt;span class="na"&gt;pre_stop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;./scripts/flush_cache.sh"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;./scripts/backup_data.sh"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;curl"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-X"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://monitoring.example.com/notify_shutdown"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How It Works&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Shutdown Initiated&lt;/strong&gt;: Container receives shutdown signal (e.g., &lt;code&gt;docker compose down&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-Stop Sequence&lt;/strong&gt;: Hooks execute in order:

&lt;ul&gt;
&lt;li&gt;Flush application cache&lt;/li&gt;
&lt;li&gt;Backup important data&lt;/li&gt;
&lt;li&gt;Notify monitoring system&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Stops&lt;/strong&gt;: After hooks complete, container proceeds with shutdown&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Practical Use Cases for Lifecycle Hooks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Post-Start Tasks
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Database Migration Example&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&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;myapp&lt;/span&gt;
    &lt;span class="na"&gt;post_start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;python"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manage.py"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;migrate"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;python"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manage.py"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;collectstatic"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--noinput"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Service Health Check&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&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;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;backend&lt;/span&gt;
    &lt;span class="na"&gt;post_start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;./scripts/wait-for-db.sh"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;./scripts/initialize-cache.sh"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pre-Stop Tasks
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Graceful Shutdown Example&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&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;worker&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;worker-service&lt;/span&gt;
    &lt;span class="na"&gt;pre_stop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;./scripts/finish_pending_jobs.sh"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;./scripts/save_metrics.sh"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cleanup Process&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&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;cache&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&lt;/span&gt;
    &lt;span class="na"&gt;pre_stop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;redis-cli"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;save"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&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;./backup-redis.sh"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices and Tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always include error checking in hook scripts&lt;/li&gt;
&lt;li&gt;Log hook execution results for debugging&lt;/li&gt;
&lt;li&gt;Consider setting appropriate timeouts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use root privileges only when necessary&lt;/li&gt;
&lt;li&gt;Keep privileged operations in hooks rather than main container&lt;/li&gt;
&lt;li&gt;Validate and sanitize any external input used in hooks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep hooks lightweight and efficient&lt;/li&gt;
&lt;li&gt;Avoid long-running operations in hooks&lt;/li&gt;
&lt;li&gt;Consider parallel execution when possible&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Version Compatibility
&lt;/h2&gt;

&lt;p&gt;Lifecycle hooks require Docker Compose v2.30.0 or newer. Before implementing hooks, ensure your environment meets these requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose version  &lt;span class="c"&gt;# Should show 2.30.0 or higher&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker Compose lifecycle hooks provide a powerful and secure way to manage container lifecycle events. By separating privileged operations and lifecycle-specific tasks into hooks, developers can create more maintainable and secure containerized applications. The ability to execute specific commands during start and stop events, combined with flexible permission handling, makes hooks an essential tool in modern container orchestration.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/how-tos/lifecycle/" rel="noopener noreferrer"&gt;Docker Compose Lifecycle Hooks Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/docker/compose/releases/tag/v2.30.0" rel="noopener noreferrer"&gt;Docker Compose Release Notes v2.30.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>containers</category>
      <category>development</category>
    </item>
    <item>
      <title>Container Anti-Patterns: Common Docker Mistakes and How to Avoid Them.</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Tue, 29 Oct 2024 09:21:40 +0000</pubDate>
      <link>https://dev.to/idsulik/container-anti-patterns-common-docker-mistakes-and-how-to-avoid-them-4129</link>
      <guid>https://dev.to/idsulik/container-anti-patterns-common-docker-mistakes-and-how-to-avoid-them-4129</guid>
      <description>&lt;p&gt;Containerization has transformed how developers package and deploy applications. While Docker simplifies this process, many developers unknowingly adopt patterns that reduce efficiency, security, or scalability. Let’s explore some common Docker anti-patterns and how to sidestep them for optimized, secure containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Using a Large Base Image Unnecessarily&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Larger base images, like ubuntu or &lt;code&gt;centos&lt;/code&gt;, are tempting for their flexibility but can lead to bloated containers. This slows down image pull and deploy times and increases attack surface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Opt for lightweight images like &lt;code&gt;alpine&lt;/code&gt; or distro-less images if they meet your needs. Start with the smallest image that provides necessary dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Building Containers as Root&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Running containers as root exposes the host system to vulnerabilities if attackers manage to access a container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Use Docker’s &lt;code&gt;USER&lt;/code&gt; instruction to define a non-root user within your &lt;code&gt;Dockerfile&lt;/code&gt;. This reduces the container’s permissions, minimizing potential security risks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Failing to Optimize Layers in Dockerfiles&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Poorly structured &lt;code&gt;Dockerfile&lt;/code&gt; commands can create extra layers, slowing down builds and consuming more storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Consolidate related commands and use multi-stage builds where possible. For instance, combining &lt;code&gt;RUN apt-get update&lt;/code&gt; and &lt;code&gt;RUN apt-get install&lt;/code&gt; into a single &lt;code&gt;RUN&lt;/code&gt; command minimizes layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Not Clearing Cache and Unnecessary Files&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Leaving unnecessary files, like build dependencies, in your image inflates size and introduces security risks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Remove temporary files, caches, and build dependencies after installation. Use &lt;code&gt;rm -rf&lt;/code&gt; to delete anything unnecessary right after it’s used in a &lt;code&gt;RUN&lt;/code&gt; command.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Hardcoding Secrets and Credentials in Dockerfiles&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Hardcoding secrets like API keys or database credentials in Dockerfiles exposes sensitive data and can be disastrous if the image is publicly shared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Use Docker’s secrets management (or environment variables securely passed during runtime) for handling credentials. Avoid embedding secrets directly in Dockerfiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Skipping Multi-Stage Builds for Production Images&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Including build tools or source code in production images results in larger, less secure containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Use multi-stage builds to keep only the required runtime dependencies in your final image. This technique drastically reduces image size and removes unnecessary tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. &lt;strong&gt;Neglecting Health Checks&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Without defined health checks, Docker and orchestration tools (like Kubernetes) can’t detect if a container is unresponsive or in a bad state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Use &lt;code&gt;HEALTHCHECK&lt;/code&gt; to define commands that validate the container’s health. Set it to run periodically, alerting you if the container fails and allowing for automatic restarts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. &lt;strong&gt;Overusing Privileged Containers&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Running containers in privileged mode (&lt;code&gt;--privileged&lt;/code&gt;) grants them extensive host permissions, which is dangerous and rarely necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Avoid &lt;code&gt;--privileged&lt;/code&gt; unless absolutely required, and instead grant only specific capabilities using &lt;code&gt;--cap-add&lt;/code&gt; for a safer, more restricted container environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. &lt;strong&gt;Not Leveraging Caching Efficiently&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Inefficient use of caching leads to slower builds, especially if commands like &lt;code&gt;RUN apt-get update&lt;/code&gt; run every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Place less frequently changing commands at the beginning of the Dockerfile to make better use of layer caching. For package installs, combine them in a way that retains cached layers whenever possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10. &lt;strong&gt;Forgetting to Set Resource Limits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Containers without CPU or memory limits can overconsume resources, leading to instability in a production environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Use &lt;code&gt;--memory&lt;/code&gt; and &lt;code&gt;--cpus&lt;/code&gt; flags to restrict resource usage for each container. These limits prevent a single container from impacting the host system’s performance.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Avoiding these Docker anti-patterns enhances your container’s performance, security, and scalability. By adopting best practices, you can ensure your containers run lean, secure, and smoothly integrated into any infrastructure. Implement these strategies to take your Docker expertise to the next level, enabling faster and safer deployments.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>container</category>
      <category>containers</category>
      <category>development</category>
    </item>
    <item>
      <title>Dockerfile Best Practices: How to Create Efficient Containers</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Sat, 05 Oct 2024 11:24:00 +0000</pubDate>
      <link>https://dev.to/idsulik/dockerfile-best-practices-how-to-create-efficient-containers-4p8o</link>
      <guid>https://dev.to/idsulik/dockerfile-best-practices-how-to-create-efficient-containers-4p8o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the era of microservices and cloud computing, Docker has become an indispensable tool for application development and deployment. Containerization allows developers to package applications and their dependencies into a single, portable unit, ensuring predictability, scalability, and rapid deployment. However, the efficiency of your containers largely depends on how optimally your Dockerfile is written.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore best practices for creating Dockerfiles that help you build lightweight, fast, and secure containers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerfile Basics
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Is a Dockerfile?
&lt;/h3&gt;

&lt;p&gt;A Dockerfile is a text document containing a set of instructions to assemble a Docker image. Each instruction performs a specific action, such as installing packages, copying files, or defining startup commands. Proper use of Dockerfile instructions is crucial for building efficient containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Dockerfile Instructions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FROM&lt;/strong&gt;: Sets the base image for your new image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RUN&lt;/strong&gt;: Executes a command in a new layer on top of the current image and commits the result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CMD&lt;/strong&gt;: Specifies the default command to run when a container is started.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COPY&lt;/strong&gt;: Copies files and directories from the build context into the container filesystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADD&lt;/strong&gt;: Similar to COPY but with additional features like extracting archives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ENV&lt;/strong&gt;: Sets environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EXPOSE&lt;/strong&gt;: Informs Docker which ports the container listens on at runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ENTRYPOINT&lt;/strong&gt;: Configures a container to run as an executable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VOLUME&lt;/strong&gt;: Creates a mount point for external storage volumes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WORKDIR&lt;/strong&gt;: Sets the working directory for subsequent instructions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices for Writing Dockerfiles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Minimal Base Images
&lt;/h3&gt;

&lt;p&gt;The base image serves as the foundation for your Docker image. Choosing a lightweight base image can significantly reduce the final image size and minimize the attack surface.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alpine Linux&lt;/strong&gt;: A popular minimal image around 5 MB in size.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  FROM alpine:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Pros&lt;/em&gt;: Small size, security, fast downloads.&lt;br&gt;&lt;br&gt;
  &lt;em&gt;Cons&lt;/em&gt;: May require additional configuration; some packages might be missing or behave differently due to using musl instead of glibc.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scratch&lt;/strong&gt;: An empty image ideal for languages that can compile static binaries (Go, Rust).
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  FROM scratch
  COPY myapp /myapp
  CMD ["/myapp"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Reduce Layers
&lt;/h3&gt;

&lt;p&gt;Each &lt;code&gt;RUN&lt;/code&gt;, &lt;code&gt;COPY&lt;/code&gt;, and &lt;code&gt;ADD&lt;/code&gt; instruction adds a new layer to your image. Combining commands helps reduce the number of layers and the overall image size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inefficient:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; python
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Efficient:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    python &lt;span class="se"&gt;\
&lt;/span&gt;    pip &lt;span class="se"&gt;\
&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optimize Layer Caching
&lt;/h3&gt;

&lt;p&gt;Docker uses layer caching to speed up builds. The order of instructions affects caching efficiency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copy Dependency Files First&lt;/strong&gt;: Copy files that change less frequently (like &lt;code&gt;package.json&lt;/code&gt; or &lt;code&gt;requirements.txt&lt;/code&gt;) before copying the rest of the source code.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  COPY package.json .
  RUN npm install
  COPY . .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimize Changes in Early Layers&lt;/strong&gt;: Changes in early layers invalidate the cache for all subsequent layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install Dependencies Wisely
&lt;/h3&gt;

&lt;p&gt;Remove temporary files and caches after installing packages to reduce image size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manage Secrets Carefully
&lt;/h3&gt;

&lt;p&gt;Never include sensitive data (passwords, API keys) in your Dockerfile. Instead:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use BuildKit's secret mounting for build-time secrets:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Mount secret during build&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nt"&gt;--mount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret,id&lt;span class="o"&gt;=&lt;/span&gt;mysecret &lt;span class="nb"&gt;cat&lt;/span&gt; /run/secrets/mysecret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Use Docker Compose secrets for runtime secrets:
&lt;/li&gt;
&lt;/ol&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;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysecret&lt;/span&gt;
&lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mysecret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./mysecret.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Environment variables for non-sensitive configuration:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; APP_PORT=3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;External secret managers for production:&lt;/li&gt;
&lt;li&gt;HashiCorp Vault&lt;/li&gt;
&lt;li&gt;AWS Secrets Manager&lt;/li&gt;
&lt;li&gt;Azure Key Vault&lt;/li&gt;
&lt;li&gt;Docker Swarm secrets (if using Swarm mode)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Best practice: Keep secrets out of image layers and inject them at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimize Image Size
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Delete Unnecessary Files&lt;/strong&gt;: Clean up caches, logs, and temporary files &lt;strong&gt;within the same &lt;code&gt;RUN&lt;/code&gt; command&lt;/strong&gt; as the installation. This ensures that these temporary files do not persist in any intermediate layers, effectively reducing the final image size.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  RUN apt-get update &amp;amp;&amp;amp; apt-get install -y --no-install-recommends package \
      &amp;amp;&amp;amp; apt-get clean &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimize Installed Packages&lt;/strong&gt;: Install only the packages you need by using flags like &lt;code&gt;--no-install-recommends&lt;/code&gt;. This avoids pulling in unnecessary dependencies, further slimming down the image.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  RUN apt-get install -y --no-install-recommends package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; To maximize image size reduction, combine this installation with cleanup commands in the same &lt;code&gt;RUN&lt;/code&gt; statement as shown above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Optimization Tools&lt;/strong&gt;: Utilize tools like &lt;strong&gt;Docker Slim&lt;/strong&gt; which can automatically analyze and optimize your Docker images by removing unnecessary components and reducing their size without altering functionality.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Utilize .dockerignore
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;.dockerignore&lt;/code&gt; file lets you exclude files and directories from the build context, reducing the amount of data sent to the Docker daemon and protecting sensitive information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example .dockerignore:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.git
node_modules
Dockerfile
.dockerignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Employ Multi-Stage Builds
&lt;/h3&gt;

&lt;p&gt;Multi-stage builds allow you to use intermediate images and copy only the necessary artifacts into the final image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example for a Go Application:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build Stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.16-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; myapp

&lt;span class="c"&gt;# Final Image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:latest&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/myapp .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./myapp"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run as Non-Root User
&lt;/h3&gt;

&lt;p&gt;For enhanced security, avoid running applications as the root user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;adduser &lt;span class="nt"&gt;-D&lt;/span&gt; appuser
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; appuser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scan for Vulnerabilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Scanning Tools&lt;/strong&gt;: Tools like &lt;strong&gt;Trivy&lt;/strong&gt;, &lt;strong&gt;Anchore&lt;/strong&gt;, or &lt;strong&gt;Clair&lt;/strong&gt; can help identify known vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regularly Update Images&lt;/strong&gt;: Keep your base images and dependencies up to date.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Logging and Monitoring
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Direct Logs to STDOUT/STDERR&lt;/strong&gt;: This allows for easier log collection and analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrate with Monitoring Systems&lt;/strong&gt;: Use tools like Prometheus or the ELK Stack to monitor container health.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Examples and Recommendations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Optimized Dockerfile Example for a Node.js Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use the official Node.js image based on Alpine Linux&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:14-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Set the working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy package files and install dependencies&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="nt"&gt;--only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production

&lt;span class="c"&gt;# Copy the rest of the application code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Create a non-root user and switch to it&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;addgroup appgroup &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; adduser &lt;span class="nt"&gt;-S&lt;/span&gt; appuser &lt;span class="nt"&gt;-G&lt;/span&gt; appgroup
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; appuser&lt;/span&gt;

&lt;span class="c"&gt;# Expose the application port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# Define the command to run the app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "app.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pin Versions&lt;/strong&gt;: Use specific versions of base images and packages to ensure build reproducibility.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  FROM node:14.17.0-alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stay Updated&lt;/strong&gt;: Regularly update dependencies and base images to include security patches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Metadata&lt;/strong&gt;: Add &lt;code&gt;LABEL&lt;/code&gt; instructions to provide image metadata.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  LABEL maintainer="yourname@example.com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Set Proper Permissions&lt;/strong&gt;: Ensure files and directories have appropriate permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Using Root&lt;/strong&gt;: Always switch to a non-root user for running applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Creating efficient Docker images is both an art and a science. By following best practices when writing your Dockerfile, you can significantly improve the performance, security, and manageability of your containers. Continuously update your knowledge and stay informed about new tools and methodologies in the containerization ecosystem. Remember, optimization is an ongoing process, and there's always room for improvement.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>container</category>
      <category>bestpractice</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Introducing Swama: A CLI Tool for Swagger/OpenAPI Interactions</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Mon, 16 Sep 2024 09:52:19 +0000</pubDate>
      <link>https://dev.to/idsulik/introducing-swama-a-cli-tool-for-swaggeropenapi-interactions-1oea</link>
      <guid>https://dev.to/idsulik/introducing-swama-a-cli-tool-for-swaggeropenapi-interactions-1oea</guid>
      <description>&lt;p&gt;APIs have become a critical part of software development. However, working with Swagger or OpenAPI specifications can sometimes feel like a manual and repetitive process. Wouldn't it be great if you could easily interact with these API specifications directly from your terminal?&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;&lt;a href="https://github.com/idsulik/swama" rel="noopener noreferrer"&gt;Swama&lt;/a&gt;&lt;/strong&gt; comes in. Swama is a CLI tool built for developers who work with Swagger/OpenAPI specifications. It allows you to effortlessly explore, manipulate, and convert API definitions from the command line.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through Swama’s features, how to install it, and how to use it to streamline your API development process.&lt;/p&gt;




&lt;h3&gt;
  
  
  What is Swama?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/idsulik/swama" rel="noopener noreferrer"&gt;Swama&lt;/a&gt; is a command-line interface (CLI) tool designed to help developers interact with Swagger/OpenAPI definitions. It provides a simple way to list API endpoints, view detailed endpoint information, convert endpoints into &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt; commands, and more.&lt;/p&gt;

&lt;p&gt;If you are tired of manually browsing through large API definitions or testing endpoints via Swagger UI, Swama is the perfect solution to boost your productivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Swama?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No More Swagger UI&lt;/strong&gt;: Browse and explore APIs directly from the command line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint Conversion&lt;/strong&gt;: Quickly convert API endpoints into &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt; commands for easy testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filtering &amp;amp; Grouping&lt;/strong&gt;: Filter and group endpoints by method, tags, or paths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binaries for All Platforms&lt;/strong&gt;: Pre-built binaries are available for Linux, macOS, and Windows.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;p&gt;Here’s a rundown of some of Swama’s key features:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;List API Endpoints&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Swama allows you to list all available API endpoints in a Swagger or OpenAPI file. You can filter endpoints by HTTP method, tags, or specific paths using wildcard matching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama endpoints list &lt;span class="nt"&gt;--method&lt;/span&gt; GET &lt;span class="nt"&gt;--tag&lt;/span&gt; user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command lists all GET endpoints tagged with user in the specified Swagger file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfvy9aszmss9o85os4a5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfvy9aszmss9o85os4a5.png" alt="Image description" width="657" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;View Endpoint Details&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Want to know more about a specific endpoint? Swama allows you to view detailed information about any endpoint in the API specification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama endpoints view &lt;span class="nt"&gt;--endpoint&lt;/span&gt; /user &lt;span class="nt"&gt;--method&lt;/span&gt; GET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will show detailed information about the &lt;code&gt;/user&lt;/code&gt; endpoint, including its summary, request body, and response details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famr7m6deddeazp3ufbxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famr7m6deddeazp3ufbxw.png" alt="Image description" width="586" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Convert Endpoints to &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Testing an API endpoint often involves writing &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt; commands. Swama simplifies this process by allowing you to instantly convert an API endpoint into one of these commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama endpoints convert &lt;span class="nt"&gt;--file&lt;/span&gt; swagger.yaml &lt;span class="nt"&gt;--endpoint&lt;/span&gt; /api/users &lt;span class="nt"&gt;--method&lt;/span&gt; POST &lt;span class="nt"&gt;--type&lt;/span&gt; curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command converts the &lt;code&gt;POST&lt;/code&gt; &lt;code&gt;/api/users&lt;/code&gt; endpoint into a &lt;code&gt;curl&lt;/code&gt; command that you can use in your terminal.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Explore Tags&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;APIs often use tags to categorize endpoints. Swama lets you list all tags in the API specification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama tags list &lt;span class="nt"&gt;--file&lt;/span&gt; swagger.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this command, you can easily see how the API is structured and what each tag represents.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;List Servers&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Many APIs are deployed across multiple servers (staging, production, etc.). Swama makes it easy to view all the servers listed in your API definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama servers list &lt;span class="nt"&gt;--file&lt;/span&gt; swagger.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command gives you a quick overview of the environments your API is running in.&lt;/p&gt;




&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;You can install Swama using the pre-built binaries available on the &lt;a href="https://github.com/idsulik/swama/releases" rel="noopener noreferrer"&gt;GitHub releases page&lt;/a&gt;. Follow these steps to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download the latest release&lt;/strong&gt; for your platform (Linux, macOS, or Windows) from &lt;a href="https://github.com/idsulik/swama/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Move the binary to your &lt;code&gt;$PATH&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On &lt;strong&gt;Linux/macOS&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;sudo mv &lt;/span&gt;swama /usr/local/bin/
 &lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/swama
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;On &lt;strong&gt;Windows&lt;/strong&gt;: Add the binary to your system’s &lt;code&gt;PATH&lt;/code&gt; to run it globally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alternatively, you can build Swama from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/idsulik/swama
&lt;span class="nb"&gt;cd &lt;/span&gt;swama
go build &lt;span class="nt"&gt;-o&lt;/span&gt; swama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, run the following to verify the installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Getting Started with Swama
&lt;/h3&gt;

&lt;p&gt;Let’s walk through a few example commands that will get you up and running with Swama.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Listing All Endpoints
&lt;/h4&gt;

&lt;p&gt;Want to list all the endpoints in your API definition? Use the &lt;code&gt;list&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama endpoints list &lt;span class="nt"&gt;--file&lt;/span&gt; swagger.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will output all the API endpoints defined in the &lt;code&gt;swagger.yaml&lt;/code&gt; file.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Viewing Endpoint Details
&lt;/h4&gt;

&lt;p&gt;To view the details of a specific API endpoint, including methods, request bodies, and responses, use the &lt;code&gt;view&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama endpoints view &lt;span class="nt"&gt;--file&lt;/span&gt; swagger.yaml &lt;span class="nt"&gt;--endpoint&lt;/span&gt; /api/users &lt;span class="nt"&gt;--method&lt;/span&gt; GET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Convert Endpoints to Testable Commands
&lt;/h4&gt;

&lt;p&gt;One of Swama’s most powerful features is its ability to convert API endpoints into &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt; commands. For example, to convert an endpoint to a &lt;code&gt;curl&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama endpoints convert &lt;span class="nt"&gt;--file&lt;/span&gt; swagger.yaml &lt;span class="nt"&gt;--endpoint&lt;/span&gt; /api/users &lt;span class="nt"&gt;--method&lt;/span&gt; POST &lt;span class="nt"&gt;--type&lt;/span&gt; curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command converts the &lt;code&gt;POST&lt;/code&gt; &lt;code&gt;/api/users&lt;/code&gt; endpoint into a &lt;code&gt;curl&lt;/code&gt; command, making it super easy to test the API from the terminal.&lt;/p&gt;




&lt;h3&gt;
  
  
  Autocompletion for Faster Workflows
&lt;/h3&gt;

&lt;p&gt;Swama supports autocompletion for various shells like Bash and Zsh. You can enable autocompletion for faster and more efficient workflows.&lt;/p&gt;

&lt;p&gt;To generate the autocompletion script for your shell, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama completion bash &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/bash_completion.d/swama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Zsh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swama completion zsh &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.zsh/completion/_swama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to quickly navigate through Swama commands and subcommands with autocompletion.&lt;/p&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Swama brings the convenience of working with Swagger/OpenAPI definitions directly into your terminal. Whether you're listing endpoints, converting them to &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt;, or exploring tags and servers, Swama makes interacting with APIs seamless.&lt;/p&gt;

&lt;p&gt;I built Swama to solve my own frustrations with manually browsing through Swagger files and converting API endpoints for testing. I hope it makes your development experience smoother as well.&lt;/p&gt;

&lt;p&gt;By following these steps, you can simplify your interaction with API specifications, reduce manual work, and boost your productivity. &lt;/p&gt;

</description>
      <category>swagger</category>
      <category>openapi</category>
      <category>swama</category>
      <category>tooling</category>
    </item>
    <item>
      <title>A Beginner’s Guide to Docker Image for Developers</title>
      <dc:creator>Suleiman Dibirov</dc:creator>
      <pubDate>Fri, 13 Sep 2024 09:11:00 +0000</pubDate>
      <link>https://dev.to/idsulik/a-beginners-guide-to-docker-image-for-developers-27ic</link>
      <guid>https://dev.to/idsulik/a-beginners-guide-to-docker-image-for-developers-27ic</guid>
      <description>&lt;p&gt;Docker has become an essential tool for developers, simplifying the process of building, testing, and deploying applications. One of the core concepts in Docker is the &lt;strong&gt;Docker image&lt;/strong&gt;, a lightweight, standalone, and executable package that includes everything needed to run a piece of software. This guide will help beginners understand Docker images, how to create them, and why they are fundamental in modern development workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What is a Docker Image?&lt;/li&gt;
&lt;li&gt;How Docker Images Work&lt;/li&gt;
&lt;li&gt;Docker Images vs Containers&lt;/li&gt;
&lt;li&gt;Pulling and Running Images from Docker Hub&lt;/li&gt;
&lt;li&gt;Creating Your Own Docker Image&lt;/li&gt;
&lt;li&gt;Managing Docker Images&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. What is a Docker Image?
&lt;/h2&gt;

&lt;p&gt;A Docker image is essentially a blueprint for a container. It contains all the necessary components such as the application code, libraries, environment variables, configuration files, and even the operating system needed to run the application.&lt;/p&gt;

&lt;p&gt;Think of it as a snapshot or template that can be used to run containers. Once you have an image, you can use it to run one or multiple instances of a container, ensuring that your application behaves the same across different environments (development, testing, production, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How Docker Images Work
&lt;/h2&gt;

&lt;p&gt;Docker images are built layer by layer, where each layer represents a step in the process of building the image. Each layer is cached, so if a layer doesn't change, Docker can reuse it in future builds, significantly speeding up the process.&lt;/p&gt;

&lt;p&gt;For example, if you update just the application code but not the base OS or dependencies, Docker will only rebuild the layers that have changed. This is key to Docker's efficiency.&lt;/p&gt;

&lt;p&gt;Here’s a simple breakdown of how layers work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Base Layer&lt;/strong&gt;: This is typically a lightweight Linux distribution like Alpine or Ubuntu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Layer&lt;/strong&gt;: This includes the libraries and dependencies your application needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Layers&lt;/strong&gt;: Any specific configurations, environment variables, or additional tools your app requires.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Docker Images vs Containers
&lt;/h2&gt;

&lt;p&gt;A common point of confusion for beginners is the distinction between Docker images and containers. To make the concept clearer, you can think of Docker images and containers as similar to object-oriented programming concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Image&lt;/strong&gt;: This is like a &lt;strong&gt;class&lt;/strong&gt; in programming. A class defines the structure and behavior (methods and properties) but doesn't actually do anything until you create an instance of it. Similarly, a Docker image is a static blueprint that contains the instructions and dependencies for running an application, but it's not actively running by itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; A &lt;code&gt;Car&lt;/code&gt; class might define attributes like &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, and &lt;code&gt;speed&lt;/code&gt;, but it's not an actual car until you create an instance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Container&lt;/strong&gt;: This is like an &lt;strong&gt;instance of a class&lt;/strong&gt;. When you instantiate (run) a class, you get a live object that can interact with the world. Similarly, when you run a Docker image, it becomes a live Docker container that executes the application in an isolated environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; If you create an instance of the &lt;code&gt;Car&lt;/code&gt; class, say a &lt;code&gt;red sports car&lt;/code&gt;, you now have a live object that you can drive. Similarly, running a Docker image creates a running container that performs actions based on the instructions in the image.&lt;/p&gt;

&lt;p&gt;This analogy helps visualize the difference: the &lt;strong&gt;Docker image&lt;/strong&gt; is the design (class), and the &lt;strong&gt;Docker container&lt;/strong&gt; is the working, running application (instance).&lt;/p&gt;

&lt;p&gt;One more way to visualize this is to think of an image as the recipe, and the container as the actual dish created from that recipe.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Pulling and Running Images from Docker Hub
&lt;/h2&gt;

&lt;p&gt;Docker Hub is a public registry where developers can share images. You can easily pull existing images from Docker Hub to run in your environment.&lt;/p&gt;

&lt;p&gt;For example, to run an Nginx web server, you can pull and run the official Nginx image with just a few commands:&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;# Pull the Nginx image from Docker Hub&lt;/span&gt;
docker pull nginx

&lt;span class="c"&gt;# Run the Nginx image as a container&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker pull nginx&lt;/code&gt;: Downloads the latest Nginx image from Docker Hub.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker run -d -p 8080:80 nginx&lt;/code&gt;: Runs the container in detached mode (&lt;code&gt;-d&lt;/code&gt;), exposing port 80 in the container to port 8080 on the host.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, if you visit &lt;code&gt;http://localhost:8080&lt;/code&gt;, you should see the Nginx welcome page.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Creating Your Own Docker Image
&lt;/h2&gt;

&lt;p&gt;While pulling images from Docker Hub is useful, developers often need to create custom images. This is where the &lt;strong&gt;Dockerfile&lt;/strong&gt; comes in. A Dockerfile is a script containing a series of instructions on how to build a Docker image.&lt;/p&gt;

&lt;p&gt;Here’s an example Dockerfile for a basic Go application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start with a base image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.18&lt;/span&gt;

&lt;span class="c"&gt;# Set the working directory inside the container&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy the Go module files&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod ./&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.sum ./&lt;/span&gt;

&lt;span class="c"&gt;# Download dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go mod download

&lt;span class="c"&gt;# Copy the source code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Build the application&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; myapp

&lt;span class="c"&gt;# Command to run the application&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./myapp"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Building the Docker Image
&lt;/h3&gt;

&lt;p&gt;Once you have your Dockerfile ready, you can build your Docker image using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-go-app &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tells Docker to build the image from the Dockerfile in the current directory (&lt;code&gt;.&lt;/code&gt;) and tag it as &lt;code&gt;my-go-app&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the Docker Image
&lt;/h3&gt;

&lt;p&gt;To run the image you just built as a 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 run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 my-go-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command starts a container from the &lt;code&gt;my-go-app&lt;/code&gt; image and maps port 8080 of the container to port 8080 on the host.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Managing Docker Images
&lt;/h2&gt;

&lt;p&gt;Docker provides several commands to help manage your images.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Listing images&lt;/strong&gt;: To see a list of all Docker images on your system, run:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Removing images&lt;/strong&gt;: If you no longer need an image, you can remove it with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker rmi &amp;lt;image-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pruning unused images&lt;/strong&gt;: Docker also provides a way to clean up unused images:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;p&gt;This command will remove dangling images (images that are not tagged or associated with any container).&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker images are a fundamental part of the Docker ecosystem, serving as the blueprint for containers. As a developer, understanding how to pull, create, and manage Docker images is crucial for building and shipping applications in a reliable and efficient manner.&lt;/p&gt;

&lt;p&gt;Whether you're pulling official images from Docker Hub or creating custom ones using a Dockerfile, Docker images help ensure that your applications run consistently across different environments. With this guide, you should have a solid foundation to start working with Docker images in your development workflow. &lt;/p&gt;

</description>
      <category>docker</category>
      <category>container</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
