<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>wigum::website - Docker</title>
    <subtitle>William Guimont-Martin’s research in robotics, AI, and 3D perception, alongside software projects, technical articles, papers, and creative writing.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://willguimont.com/tags/docker/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://willguimont.com/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-09-07T00:00:00+00:00</updated>
    <id>https://willguimont.com/tags/docker/atom.xml</id>
    <entry xml:lang="en">
        <title>Docker Workshop</title>
        <published>2025-09-07T00:00:00+00:00</published>
        <updated>2025-09-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            William Guimont-Martin
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://willguimont.com/blog/docker-workshop/"/>
        <id>https://willguimont.com/blog/docker-workshop/</id>
        
        <content type="html" xml:base="https://willguimont.com/blog/docker-workshop/">&lt;p&gt;Docker and containerization have revolutionized the way applications are developed, deployed, and managed.
Containers provide a lightweight and efficient way to package applications and their dependencies, ensuring consistency across different environments.&lt;/p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;p&gt;The original workshop was designed to use with a virtual machine (&lt;a rel=&quot;external&quot; href=&quot;https://github.com/willGuimont/IFT2001-Docker&quot;&gt;willGuimont/IFT2001-Docker&lt;/a&gt;).
While you can follow the instructions below to set up the virtual machine, you can also choose to follow the workshop using Docker.&lt;/p&gt;
&lt;p&gt;Follow these steps to prepare your environment.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a rel=&quot;external&quot; href=&quot;https://docs.docker.com/engine/install/ubuntu/&quot;&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker run -it --rm ubuntu:latest bash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In the Docker container, run:
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;apt update &amp;amp;&amp;amp; apt install -y git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mkdir .atelier &amp;amp;&amp;amp; cd .atelier &amp;amp;&amp;amp; git clone https://github.com/willGuimont/IFT2001-Docker ateliers-iftglo-2001&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd ateliers-iftglo-2001&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;./helper/install.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;python3 ./helper/prepare_bashrc.py &amp;amp;&amp;amp; source ~/.bashrc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy the files in your home directory: &lt;code&gt;cd ~/.atelier/ateliers-iftglo-2001/files &amp;amp;&amp;amp; cp -r . ~/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;instructions&quot;&gt;Instructions&lt;/h3&gt;
&lt;p&gt;The instruction above sets up your environment for the workshop.
The grading commands are of the form &lt;code&gt;correction_nn&lt;/code&gt;, where &lt;code&gt;nn&lt;/code&gt; is an integer representing the exercise number, for example &lt;code&gt;correction_03&lt;/code&gt; for exercise 3.
Instructions for validating commands will be provided with the first question that has an expected result.&lt;/p&gt;
&lt;p&gt;To complete this workshop, you must perform each exercise directly in the terminal.
You will use the &lt;code&gt;nano&lt;/code&gt; text editor to modify the requested scripts.
To open a file with nano, run the following in the terminal.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;nano&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; test.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can then edit the file; enter&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;Hello world&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To exit nano, press &lt;kbd&gt;CTRL&lt;/kbd&gt;-&lt;kbd&gt;X&lt;/kbd&gt;, then answer &lt;code&gt;y&lt;/code&gt; to save the changes.
Run the following commands to validate that everything works:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;chmod&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; +x&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; test.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;./test.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These commands should print &lt;code&gt;Hello world&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;markdown-alert-tip&quot;&gt;
	&lt;p&gt;&lt;strong&gt;Adventurers only&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are comfortable with the command line, we encourage you to try completing this workshop using &lt;code&gt;vim&lt;/code&gt; as your text editor.
A brief introduction to &lt;code&gt;vim&lt;/code&gt; commands is available on &lt;a rel=&quot;external&quot; href=&quot;https://missing.csail.mit.edu/2020/editors/&quot;&gt;MIT’s The Missing Semester&lt;/a&gt;.
&lt;code&gt;vim&lt;/code&gt; offers many shortcuts to edit text and code very efficiently.
As a programmer, you will spend a lot of time writing code, so investing in learning &lt;code&gt;vim&lt;/code&gt; is worthwhile for the rest of your career.
There are plugins emulating &lt;code&gt;vim&lt;/code&gt; commands for most IDEs: &lt;a rel=&quot;external&quot; href=&quot;https://marketplace.visualstudio.com/items?itemName=vscodevim.vim&quot;&gt;Vim for VS Code&lt;/a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https://plugins.jetbrains.com/plugin/164-ideavim&quot;&gt;IdeaVim for JetBrains products&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please note that no assistance regarding &lt;code&gt;vim&lt;/code&gt; will be provided during this workshop.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;solutions&quot;&gt;Solutions&lt;/h3&gt;
&lt;p&gt;Proposed solutions to the exercises in these workshops are available in the following GitHub repository: &lt;a rel=&quot;external&quot; href=&quot;https://github.com/ulavalIFTGLOateliers/IFT2001-Docker&quot;&gt;ulavalIFTGLOateliers/IFT2001-Docker&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;docker&quot;&gt;Docker&lt;/h2&gt;
&lt;p&gt;After your success with &lt;a href=&quot;https://willguimont.com/blog/bash-workshop/&quot;&gt;Bash&lt;/a&gt;, your manager has given you a new mission: find a solution to the application deployment problem.
Your company frequently encounters outages due to incompatibilities between different dependency versions.
Indeed, each developer can choose the operating system they wish to work on.
Consequently, some developers use different Linux distributions (Ubuntu, Arch, Gentoo), while others prefer Windows.&lt;/p&gt;
&lt;p&gt;This situation often leads to version issues, as dependencies vary from one OS to another.
And worse, the versions used differ from those deployed on the production server.
The recurring excuse “It worked on my machine” when a developer causes a production outage has finally exasperated your manager. He is asking you to find a solution.&lt;/p&gt;
&lt;p&gt;That’s how you discover Docker, a platform that lets you build, deploy, and run applications in lightweight, isolated containers.
With Docker, you can create a specific container for each microservice, including all required libraries and dependencies.
This approach ensures that each application will run consistently, regardless of library versions used by individual developers.
Moreover, Docker allows you to reproduce the development environment on the production server, thereby eliminating issues stemming from environment differences.&lt;/p&gt;
&lt;p&gt;With Docker, you will tackle the challenge of running your company’s three main microservices.
Here are the microservices you must get working:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a web server health monitoring application written in Haskell;&lt;/li&gt;
&lt;li&gt;a document management API written in Rust, requiring a PostgreSQL database; and&lt;/li&gt;
&lt;li&gt;a Python application for visualizing web server health.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;wide-crt&quot;&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌────────────────────────────── MICROSERVICES (ARCH OVERVIEW) ───────────────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│                                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  (3) python_app (CLI)                                                                  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Image: python_app                                                                 │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Mode: --network=host (workshop)                                                   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      BACKEND_URL = http://localhost:8080                                               │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Uses: list/add endpoints, view uptime stats                                       │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            │                                                                           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            │ HTTP (JSON)                                                               │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            ▼                                                                           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  (1) status-checker (Haskell)                                                          │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Image: status-checker                                                             │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Port: 8080                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Storage: monitoring.sqlite (SQLite)                                               │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            │                                                                           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            │ HTTP health probe (/documents or /health)                                 │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            ▼                                                                           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  (2) rust_api (Actix Web)                                                              │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Image: rust_api (multi-stage)                                                     │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Port: 8081                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Env: DATABASE_URL=postgres://postgres:postgres@db                                 │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            │                                                                           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            │ SQL (Diesel)                                                              │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│            ▼                                                                           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      PostgreSQL                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Image: postgres                                                                   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Port: 5432                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│      Volume: db:/var/lib/postgresql/data                                               │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│                                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  Data Flows (top→down):                                                                │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│    python_app ──HTTP──▶ status-checker ──HTTP──▶ rust_api ──SQL──▶ PostgreSQL          │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│                                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  Summary:                                                                              │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│    - python_app only contacts status-checker.                                          │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│    - status-checker pings rust_api for availability.                                   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│    - rust_api persists documents in Postgres.                                          │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│                                                                                        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  Ports: 8080 (status-checker) | 8081 (rust_api) | 5432 (Postgres)                      │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────────────────────────────────────────────────────────────────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&quot;why-containerization&quot;&gt;Why containerization?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Isolation&lt;/strong&gt;&lt;br /&gt;
One of the main advantages of containerization is isolation.
It often happens that different applications require specific dependency versions.
With Docker, you can install different dependency versions in distinct containers, without risking conflicts or compromising other applications.
Furthermore, if you need to run applications on different operating systems, such as Ubuntu and Arch Linux, you can simply wrap them in Docker containers, avoiding the need to rewrite applications for each system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Portability&lt;/strong&gt;&lt;br /&gt;
Portability is another key advantage of Docker.
Once you have set up a development environment with all required dependencies, reproducing that configuration on other machines or for new team members becomes tedious.
Thanks to Docker, you can create an image that contains all required dependencies and configuration, which can be easily distributed and run on different platforms, whether Linux, Windows, or others.
This enables a new team member to start quickly without spending weeks configuring their environment.
It’s also an advantage when deploying applications to a server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reproducibility&lt;/strong&gt;&lt;br /&gt;
Reproducibility is also simplified with Docker.
Docker images are versioned, which means it is easy to reproduce builds identically, ensuring that development, test, and production environments are consistent.
You just need to specify the version of the Docker image used to guarantee consistency and avoid issues related to variations across environments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;&lt;br /&gt;
In terms of efficiency, Docker offers a significant advantage over virtual machines (VMs).
Unlike VMs, Docker does not need to run a full operating system for each container, which greatly reduces resource consumption.
Docker containers share the host kernel, making them lightweight and quick to start.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;br /&gt;
Docker’s surrounding community is very active and offers a multitude of preconfigured images for various popular tools and technologies such as Node.js, Python, and many others.
These preconfigured images facilitate deployment and usage of these technologies, saving developers time by avoiding manual environment setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Industry&lt;/strong&gt;&lt;br /&gt;
Finally, it’s important to emphasize that Docker has become a de facto standard in the software development industry.
Many companies use Docker for development, testing, and deployment of their applications.
Docker is now an essential tool for software developers.&lt;/p&gt;
&lt;h3 id=&quot;what-is-containerization&quot;&gt;What is containerization?&lt;/h3&gt;
&lt;p&gt;Docker is an open-source software platform that lets you create, deploy, and run applications in lightweight, isolated containers.
A Docker container is a runtime unit that encapsulates an application together with all of its necessary elements, such as libraries, dependencies, and configuration files.
These containers are self-contained and portable, meaning they can run consistently across different systems, whether a development, test, or production environment.&lt;/p&gt;
&lt;p&gt;Docker is similar to a virtual machine that isolates an application from the host system.
However, Docker is much more efficient than a VM, which requires a full operating system for each instance.
Docker instead shares the host operating system’s &lt;code&gt;kernel&lt;/code&gt;, saving resources and making containers faster to start and run.&lt;/p&gt;
&lt;p&gt;Here is some Docker terminology.
You do not have to read the advanced sections to complete this workshop.
As a supplement, you can watch the video &lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=J0NuOlA2xDc&quot;&gt;“Never install locally”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Image&lt;/strong&gt;&lt;br /&gt;
An image contains the filesystem and user-space components required by the application: binaries, libraries, dependencies, configuration files, and often a Linux distribution’s userland.
It does not contain its own Linux kernel.
Docker images are typically created from files called &lt;code&gt;Dockerfile&lt;/code&gt; that specify the steps to build the image.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br /&gt;
A Dockerfile is a text file that contains the instructions to build a Docker image.
It specifies the image layers, dependencies to install, files to include, and commands to run during image construction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Container&lt;/strong&gt;&lt;br /&gt;
A Docker container is a running instance of a Docker image.
It is an isolated environment that runs the application with its dependencies.
Containers are lightweight, portable, and self-contained, which makes them easy to deploy across different machines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Registry&lt;/strong&gt;&lt;br /&gt;
A Docker registry is a centralized repository that stores and manages Docker images.
The default public registry is &lt;a rel=&quot;external&quot; href=&quot;https://hub.docker.com/&quot;&gt;Docker Hub&lt;/a&gt;, where you can find many ready-to-use images.
You can also create and use your own private registry to store your own images.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Union filesystem (advanced concepts)&lt;/strong&gt;&lt;br /&gt;
The &lt;em&gt;Union Filesystem&lt;/em&gt;, also known as &lt;em&gt;UnionFS&lt;/em&gt; or &lt;em&gt;OverlayFS&lt;/em&gt;, is a technology used by Docker to manage images and container layers efficiently.
The &lt;em&gt;Union Filesystem&lt;/em&gt; allows you to overlay multiple file systems into a single logical view without physically merging them.
This means Docker images and containers can share and reuse common file layers, saving storage space.
It also speeds up image builds by caching layers already built.
When a container starts, a new read-write layer is added on top of the image layers, enabling container-specific changes without affecting others.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;cgroups (advanced concepts)&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;cgroups&lt;/code&gt;, or &lt;em&gt;control groups&lt;/em&gt;, are a Linux kernel feature used by Docker to limit and manage system resources used by containers.
&lt;code&gt;cgroups&lt;/code&gt; allow control of resources such as CPU, memory, disk bandwidth, and network, ensuring balanced and fair resource usage among containers.
Docker uses &lt;code&gt;cgroups&lt;/code&gt; to set limits and quotas on resources allocated to each container, ensuring isolation and predictable performance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Namespaces (advanced concepts)&lt;/strong&gt;&lt;br /&gt;
Namespaces are a Linux kernel feature that isolates system resources among processes.
Docker uses several types of namespaces to provide isolation between containers, including the PID namespace (process isolation), the network namespace (network isolation), the user namespace (user isolation), and the mount namespace (mount point isolation).
These namespaces ensure that each container has its own isolated view of the system, preventing processes in one container from interfering with others or with the host system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chroot jail (advanced concepts)&lt;/strong&gt;&lt;br /&gt;
Chroot, or change root, is a Unix/Linux feature that changes a process’s root directory and limits its access to the file system.
Docker uses chroot to create an isolated environment inside the container, where the container’s root directory becomes the starting point for all file paths.
This limits the container’s access to files and directories outside its isolated environment, thereby strengthening security and isolation.&lt;/p&gt;
&lt;h2 id=&quot;containers-manually&quot;&gt;Containers manually&lt;/h2&gt;
&lt;p&gt;To clearly illustrate what Docker does, we will manually build a simplified container without using Docker.
This section is inspired by &lt;a rel=&quot;external&quot; href=&quot;https://github.com/p8952/bocker&quot;&gt;p8952/bocker: Docker implemented in around 100 lines of bash&lt;/a&gt;.
In a terminal, enter the following commands:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Verify that neofetch is not installed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; The following command should raise an error; do not install the package&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;neofetch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Folder for containers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ~/containers&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt; cd&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ~/containers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Build the container&amp;#39;s filesystem&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; apt&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; update&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt; sudo&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; apt&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; debootstrap&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; debootstrap&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; jammy&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./ubuntu-container&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; http://archive.ubuntu.com/ubuntu/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Create an isolated environment (namespace)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; unshare&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-uts&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-pid&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-mount&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-ipc&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-fork&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Mount process, system, device, and temp folders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; proc&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; none&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./ubuntu-container/proc/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; sysfs&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; none&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./ubuntu-container/sys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bind&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; /dev&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./ubuntu-container/dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bind&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; /tmp&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./ubuntu-container/tmp/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;cp&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; /etc/apt/sources.list&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./ubuntu-container/etc/apt/sources.list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Use chroot to launch a shell in the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;chroot&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./ubuntu-container/&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; /bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; and there you go, you&amp;#39;re in an isolated container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Install neofetch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;apt&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; update&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;apt&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; neofetch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Test neofetch; the command works!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;neofetch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; You can run commands in the container here.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Exit the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;exit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Exit unshare&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;exit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; If we try neofetch again, the command is not found.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; We have indeed isolated the container!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;neofetch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, there is no magic in containers.
There is no magic in a container: at its core, Linux provides mechanisms such as namespaces, filesystem isolation, and cgroups.
Docker packages these mechanisms behind a convenient image, networking, storage, and lifecycle-management interface.&lt;/p&gt;
&lt;h2 id=&quot;docker-basics&quot;&gt;Docker basics&lt;/h2&gt;
&lt;h3 id=&quot;exercise-01-running-a-prebuilt-image&quot;&gt;Exercise 01 – Running a prebuilt image&lt;/h3&gt;
&lt;p&gt;Run the Docker image &lt;code&gt;hello-world&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;To run a Docker image, use the &lt;code&gt;run&lt;/code&gt; command.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; image-name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the command works, you will see a message displayed.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; hello-world&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;To execute a command in the container, specify the command at the end of &lt;code&gt;run&lt;/code&gt;.
In the following examples, we pass &lt;code&gt;bash -c &#39;echo &quot;Hello world&quot;&#39;&lt;/code&gt; which interprets the string in the Bash interpreter.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Prints &amp;#39;Hello world&amp;#39; in an ubuntu container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ubuntu&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bash&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;echo &amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Prints information about the host system&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; /etc/os-release&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Prints information from a container running Arch Linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; archlinux&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bash&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;cat /etc/os-release&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;To launch an interactive command (such as a shell), use the &lt;code&gt;-it&lt;/code&gt; flag.
The &lt;code&gt;--rm&lt;/code&gt; flag removes the container once it exits.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; archlinux&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bash&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;exercise-02-container-management&quot;&gt;Exercise 02 – Container management&lt;/h3&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;To see running containers: &lt;code&gt;docker ps&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To stop a container: &lt;code&gt;docker stop container_id&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note that the command may take some time to run.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Launch an interactive terminal with Docker;&lt;/li&gt;
&lt;li&gt;Open another terminal and inspect running containers;&lt;/li&gt;
&lt;li&gt;Stop the Docker container from the second terminal.&lt;/li&gt;
&lt;/ol&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; In the first terminal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; archlinux&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; In the second terminal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; stop&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; or&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; id&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;h3 id=&quot;exercise-03-inspecting-a-running-container&quot;&gt;Exercise 03 – Inspecting a running container&lt;/h3&gt;
&lt;p&gt;Containers often run in the background.
Docker provides several commands to inspect and interact with running containers.&lt;/p&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;To display the output produced by a container:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; logs&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; container_name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To execute a command inside a running container:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; exec&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; container_name&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; command&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, to open an interactive shell:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; exec&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; container_name&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bash&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, docker inspect displays detailed information about a Docker object, including its network configuration, mounted filesystems, environment variables, and process configuration:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; inspect&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; container_name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Launch an nginx container in the background:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-name&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-server&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 8080:80&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; nginx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Verify that the container is running.&lt;/li&gt;
&lt;li&gt;Display the container’s logs.&lt;/li&gt;
&lt;li&gt;Open an interactive shell inside the running container.&lt;/li&gt;
&lt;li&gt;From inside the container, inspect the files in /usr/share/nginx/html.&lt;/li&gt;
&lt;li&gt;Use docker inspect to find the container’s IP address.&lt;/li&gt;
&lt;li&gt;Stop and remove the container.&lt;/li&gt;
&lt;/ol&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Verify that the container is running&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Display its logs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; logs&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Execute Bash inside the existing container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; exec&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-server&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Inside the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;ls&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; /usr/share/nginx/html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;exit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Inspect the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; inspect&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Find the IP address&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; inspect&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-format&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;    web-server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Stop and remove it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; stop&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; rm&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;docker run&lt;/code&gt; creates a new container, whereas &lt;code&gt;docker exec&lt;/code&gt; executes another process inside an already running container.
This distinction is useful when debugging services running in the background.&lt;/p&gt;
&lt;/details&gt;
&lt;h3 id=&quot;exercise-04-postgresql-database&quot;&gt;Exercise 04 – PostgreSQL database&lt;/h3&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;To set environment variables in a container, use the &lt;code&gt;-e&lt;/code&gt; flag.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; HELLO=hello&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; archlinux&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; sh&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;echo $HELLO&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;To open a network port, use the &lt;code&gt;-p host:docker&lt;/code&gt; flag, where &lt;code&gt;host&lt;/code&gt; is the port number on the host and &lt;code&gt;docker&lt;/code&gt; is the port number inside the container.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 127.0.0.1:8080:80&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; nginx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; You can access the port via the URL http://localhost:8080/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; http://localhost:8080/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Launch a PostgreSQL database with Docker.&lt;/p&gt;
&lt;p&gt;Requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Image name: &lt;code&gt;postgres&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the environment variable &lt;code&gt;POSTGRES_PASSWORD=postgres&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Map Docker port 5432 to host port 5432&lt;/li&gt;
&lt;li&gt;Leave this container running.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; POSTGRES_PASSWORD=postgres&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 5432:5432&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; postgres&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; or&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-name&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; postgres&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; POSTGRES_PASSWORD=postgres&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 5432:5432&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; postgres&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;h2 id=&quot;dockerfile&quot;&gt;Dockerfile&lt;/h2&gt;
&lt;p&gt;Dockerfiles are configuration files used to create custom Docker images.
They allow you to define, reproducibly and automatically, an application’s runtime environment inside a Docker container.&lt;/p&gt;
&lt;p&gt;A Dockerfile contains a series of instructions that specify the steps needed to build a Docker image.
These instructions include actions such as selecting the base image, installing dependencies, configuring environment variables, copying files, running commands, and more.&lt;/p&gt;
&lt;p&gt;Here is an annotated example Dockerfile for a Python application.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Use the Python 3.9 slim base image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; python:3.9-slim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Set the working directory inside the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Specifies the directory for RUN, CMD, ENTRYPOINT, COPY, and ADD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Copy requirements.txt from the host into the Docker container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; requirements.txt .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Run a Bash command to install Python dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; pip install -r requirements.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Copy the source code into the Docker container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Set the default command when the container starts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;CMD&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;app.py&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To build the image, use &lt;code&gt;docker build -t &amp;lt;tag&amp;gt; .&lt;/code&gt;.
The &lt;code&gt;-t &amp;lt;tag&amp;gt;&lt;/code&gt; argument gives the image the name &lt;code&gt;&amp;lt;tag&amp;gt;&lt;/code&gt;.
For the previous application, you could use &lt;code&gt;docker build -t python-app .&lt;/code&gt;.
Note that the order of instructions matters.&lt;/p&gt;
&lt;p&gt;It is crucial to define the order of operations in a Dockerfile due to how Docker builds images.
Each instruction in the Dockerfile creates a new layer in the Docker image, and the order can significantly impact build efficiency and performance.&lt;/p&gt;
&lt;p&gt;Docker uses a cache to speed up image builds.
When you run an instruction, Docker checks whether that instruction has already been executed in a previous layer.
If so and the parameters are identical, Docker reuses the cached layer instead of rebuilding it.
This saves build time.
However, if you modify an instruction higher up in the Dockerfile, all subsequent instructions will have their cache invalidated and must be rebuilt.
&lt;strong&gt;For example, if you perform resource-intensive operations such as compiling code that changes whenever you modify the source, it can be preferable to place those steps towards the end of the Dockerfile to benefit from caching as much as possible.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;exercise-05-haskell-service-dockerfile&quot;&gt;Exercise 05 – Haskell service Dockerfile&lt;/h3&gt;
&lt;p&gt;Use the &lt;code&gt;README.md&lt;/code&gt; in the folder &lt;code&gt;~/Applications/status-checker&lt;/code&gt; to write a Dockerfile that runs the Haskell application.&lt;/p&gt;
&lt;p&gt;Requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base image &lt;code&gt;haskell:9.0-buster&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;stack setup --install-ghc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Workdir &lt;code&gt;/app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy the source code into &lt;code&gt;/app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;stack build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Launch the server with &lt;code&gt;stack run&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, start the container exposing port 8080.
If everything works, you should be able to run:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; http://localhost:8080/endpoints&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Expected response&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Or&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Leave this container running.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;
&lt;p&gt;Dockerfile:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; haskell:9.0-buster&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; stack setup --install-ghc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; stack build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;CMD&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Execution:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; status-checker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 8080:8080&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; status-checker&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;h3 id=&quot;exercise-06-python-application-dockerfile&quot;&gt;Exercise 06 – Python application Dockerfile&lt;/h3&gt;
&lt;p&gt;Use the &lt;code&gt;README.md&lt;/code&gt; in the folder &lt;code&gt;~/Applications/python_app&lt;/code&gt; to write a Dockerfile that runs the Python application.&lt;/p&gt;
&lt;p&gt;Then, launch the application interactively and with the correct network mode.&lt;/p&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
	&lt;p&gt;This application will need to access your computer’s local network to make requests to the container from the previous exercise; to keep this exercise simple, use &lt;code&gt;--network=&quot;host&quot;&lt;/code&gt; when running the container.&lt;/p&gt;
&lt;p&gt;Host networking makes the container share the host’s network stack.
This is convenient here, but it reduces network isolation and is not the usual way for containers to communicate with each other.
Later, Docker Compose will place the containers on a shared Docker network, where services can communicate directly using their service names.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If everything works, you should be able to use the application to add URLs to monitor and see the results.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;
&lt;p&gt;Dockerfile:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; python:3.9-slim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; requirements.txt .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; pip install -r requirements.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;CMD&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;main.py&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Execution:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; python_app&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-network=host&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; python_app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;h2 id=&quot;advanced-docker&quot;&gt;Advanced Docker&lt;/h2&gt;
&lt;p&gt;Sometimes, you may need to create more complex Docker images.
Here, we will explore two advanced Docker features: multi-stage builds and volumes.&lt;/p&gt;
&lt;h3 id=&quot;multi-stage-image-builds&quot;&gt;Multi-stage image builds&lt;/h3&gt;
&lt;p&gt;Multi-stage builds are an advanced Docker feature that enables optimized image creation using several distinct stages in the build process.
This separates build and production stages, often resulting in final images that are lighter and more secure by minimizing what remains in the final image.&lt;/p&gt;
&lt;p&gt;For example, for a JavaScript React application, we can split the build into two stages.&lt;/p&gt;
&lt;p&gt;Create the application:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;npx&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; create-react-app&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; my-app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dockerfile:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Stage 1: Build the application&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Use `as build` to name this build stage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; node:14-alpine &lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;as&lt;/span&gt;&lt;span&gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; package*.json ./&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; npm install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; npm run build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Stage 2: Prepare the server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Here, we start a new image from scratch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; nginx:alpine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Copy the compiled app from the previous stage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; --from=build /app/build /usr/share/nginx/html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;EXPOSE&lt;/span&gt;&lt;span&gt; 80&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;CMD&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;nginx&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;-g&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;daemon off;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To run:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-app&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 80:80&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; web-app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;exercise-07-rust-multi-stage-build&quot;&gt;Exercise 07 – Rust multi-stage build&lt;/h3&gt;
&lt;p&gt;Use the &lt;code&gt;README.md&lt;/code&gt; in the folder &lt;code&gt;~/Applications/rust_api&lt;/code&gt; to write a Dockerfile that runs the application.&lt;/p&gt;
&lt;p&gt;Requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Launch the PostgreSQL database from a previous exercise;&lt;/li&gt;
&lt;li&gt;Create a first stage to compile the Rust code;&lt;/li&gt;
&lt;li&gt;Create a second stage to run the code;
&lt;ul&gt;
&lt;li&gt;Start this image from &lt;code&gt;debian:bullseye-slim&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Install the package &lt;code&gt;libpq-dev&lt;/code&gt; with &lt;code&gt;apt update; apt install -y libpq-dev&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Set the environment variable &lt;code&gt;DATABASE_URL=postgres://postgres:postgres@localhost&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy &lt;code&gt;/app/target/release/rust_api&lt;/code&gt; from the previous stage;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run the container with &lt;code&gt;--network=host&lt;/code&gt; and expose the correct port;&lt;/li&gt;
&lt;li&gt;Test that everything works with &lt;code&gt;curl http://localhost:8081/documents&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; rust:latest &lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;AS&lt;/span&gt;&lt;span&gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; cargo build --release&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; debian:bullseye-slim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; apt update; apt install -y libpq-dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; --from=build /app/target/release/rust_api ./rust_api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;ENV&lt;/span&gt;&lt;span&gt; DATABASE_URL=postgres://postgres:postgres@db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;CMD&lt;/span&gt;&lt;span&gt; ./rust_api&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Execution&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; POSTGRES_PASSWORD=postgres&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 5432:5432&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; postgres&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; rust_api&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-network=host&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; rust_api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Validate that the server works&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; http://localhost:8081/documents&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;h3 id=&quot;volumes-and-bind-mounts&quot;&gt;Volumes and bind mounts&lt;/h3&gt;
&lt;p&gt;Containers have a writable filesystem, but this filesystem belongs to the container.
If the container is removed, the data written inside it is also removed.
Docker provides mounts to store data outside the container’s filesystem.&lt;/p&gt;
&lt;p&gt;There are two common types of mounts: &lt;strong&gt;volumes&lt;/strong&gt; and &lt;strong&gt;bind mounts&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;volume&lt;/strong&gt; is storage managed by Docker. You give the volume a name, and Docker decides where the data is stored on the host:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; database-data:/var/lib/postgresql/data&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; postgres&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;database-data&lt;/code&gt; is a Docker volume and &lt;code&gt;/var/lib/postgresql/data&lt;/code&gt; is the directory where PostgreSQL sees it inside the container.
The data remains available even if the container is removed.
Volumes are therefore particularly useful for persistent application data such as databases.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;bind mount&lt;/strong&gt; directly maps an existing file or directory from the host filesystem into the container:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; ./src:/app/src&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; my-app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;./src&lt;/code&gt; is a directory on the host and &lt;code&gt;/app/src&lt;/code&gt; is where it appears inside the container.
Changes made on either side are immediately visible on the other side.&lt;/p&gt;
&lt;p&gt;Volumes are generally appropriate for persistent application data.
Bind mounts are useful when the container must directly access files from the host, for example source code, configuration files, or datasets.&lt;/p&gt;
&lt;p&gt;For example, we can persist PostgreSQL data using a named volume:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; POSTGRES_PASSWORD=postgres&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 5432:5432&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;    -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; postgres-data:/var/lib/postgresql/data&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;    postgres&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Docker creates and manages &lt;code&gt;postgres-data&lt;/code&gt;.
Removing the container does not remove the volume.&lt;/p&gt;
&lt;p&gt;During development, we can instead use a bind mount to expose the Python application’s source code directly inside the container.
This avoids rebuilding the image whenever the source code changes.&lt;/p&gt;
&lt;p&gt;A DockerfileDev can therefore omit the source code:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; python:3.9-slim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;WORKDIR&lt;/span&gt;&lt;span&gt; /app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;COPY&lt;/span&gt;&lt;span&gt; requirements.txt .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;RUN&lt;/span&gt;&lt;span&gt; pip install -r requirements.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; We removed the line COPY . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-5&quot;&gt;CMD&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;bash&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Build and run it with:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; python_app&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; DockerfileDev&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; .&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-rm&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; .:/app&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; python_app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; In the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; main.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Modify the source code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; main.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Changes are reflected in the container&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thus, you can reuse the same image even if the source code has changed.&lt;/p&gt;
&lt;h2 id=&quot;extras&quot;&gt;Extras&lt;/h2&gt;
&lt;p&gt;Some additional Docker features and tools that may be useful in your projects.&lt;/p&gt;
&lt;h3 id=&quot;cleanup&quot;&gt;Cleanup&lt;/h3&gt;
&lt;p&gt;When using Docker, it is important to consider the storage used by images, containers, volumes, and other Docker artifacts.
Poor storage management can lead to excessive disk usage and make Docker maintenance and resource management difficult.
Docker provides several &lt;code&gt;prune&lt;/code&gt; commands to remove unused containers and images.
To clean up various Docker artifacts, the command &lt;code&gt;docker system prune -a -f&lt;/code&gt; removes all unused resources.&lt;/p&gt;
&lt;h3 id=&quot;docker-compose&quot;&gt;Docker Compose&lt;/h3&gt;
&lt;p&gt;Docker Compose is a tool that allows you to easily define and manage multi-container applications.
It simplifies deployment and orchestration of Docker containers using a simple, readable configuration file.&lt;/p&gt;
&lt;p&gt;With Docker Compose, you can specify services, networks, volumes, and other configurations needed to run an application composed of multiple containers.
You can also define dependencies among containers, environment variables, exposed ports, etc.&lt;/p&gt;
&lt;p&gt;Docker Compose uses a YAML configuration file to describe the application’s infrastructure.
This file contains sections such as &lt;em&gt;services&lt;/em&gt;, &lt;em&gt;networks&lt;/em&gt;, &lt;em&gt;volumes&lt;/em&gt;, etc., where you can define the different parts of your application and their configurations.&lt;/p&gt;
&lt;p&gt;Here is an example &lt;code&gt;docker-compose.yml&lt;/code&gt; for the Rust application that launches both the server and the PostgreSQL database:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; List of containers to launch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;ervices&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Database container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; We find many of the same parameters as with `docker run`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;  d&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;b&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Image to launch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    i&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;mage&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;ostgres:18&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Restart the database if the container stops&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    r&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;estart&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; a&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;lways&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Environment variables passed to PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    e&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;nvironment&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      P&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;OSTGRES_USER&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;ostgres&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      P&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;OSTGRES_PASSWORD&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;ostgres&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Store the database outside the container using a named volume&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    v&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;olumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; d&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;b:/var/lib/postgresql/data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Test whether PostgreSQL is ready to accept connections&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Starting a container does not necessarily mean that the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; application inside it is ready yet.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    h&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;ealthcheck&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      t&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;est&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;CMD-SHELL&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;pg_isready -U postgres&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      i&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;nterval&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 5&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      t&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;imeout&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 5&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      r&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;etries&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-9&quot;&gt; 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      s&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;tart_period&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; 5&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;  #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Rust server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;  a&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;pi&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Build the Dockerfile in the directory containing compose.yaml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    b&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;uild&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-9&quot;&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Start the API only once the database healthcheck succeeds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    d&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;epends_on&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      d&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;b&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;        c&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;ondition&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; s&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;ervice_healthy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Map host port 8081 to container port 8081&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    p&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;orts&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;8081:8081&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Containers in the same Compose application share a network.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Services can reach each other using their service name.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Therefore, the database is available at hostname `db`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; rather than `localhost`.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    e&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;nvironment&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;      D&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;ATABASE_URL&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; p&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;ostgres://postgres:postgres@db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-6 z-l-i z-d-3 z-d-i&quot;&gt; Named volumes used by the application&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;olumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;  d&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;b&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;    d&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;river&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; l&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt;ocal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run with:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-1&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; compose&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-2&quot;&gt; up&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt; -&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-8&quot;&gt;-build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compose creates a default network for the application.
The &lt;code&gt;api&lt;/code&gt; container can therefore resolve &lt;code&gt;db&lt;/code&gt; as a hostname and connect directly to the PostgreSQL container.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;depends_on&lt;/code&gt; normally controls startup order only.
By combining it with the database healthcheck and condition: &lt;code&gt;service_healthy&lt;/code&gt;, Compose waits until PostgreSQL is actually ready to accept connections before starting the API.&lt;/p&gt;
&lt;h3 id=&quot;podman&quot;&gt;Podman&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://podman.io/&quot;&gt;Podman&lt;/a&gt; is an open-source alternative to Docker.
Docker and Podman are two popular containerization tools that share similar features but differ in architecture and security approach.
Docker uses a client-server architecture, where the Docker daemon runs as a separate process and Docker commands are executed via the CLI.
In contrast, Podman uses a daemonless architecture, meaning it runs directly as a regular user and does not require a separate daemon process.
Thus, Podman can run without special privileges, limiting potential risks associated with running as superuser. See &lt;a rel=&quot;external&quot; href=&quot;https://www.redhat.com/en/topics/containers/what-is-podman&quot;&gt;What is podman?&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;Podman also offers tools to manage &lt;em&gt;pods&lt;/em&gt;, a topic outside the scope of this workshop.&lt;/p&gt;
&lt;h3 id=&quot;kubernetes&quot;&gt;Kubernetes&lt;/h3&gt;
&lt;p&gt;Kubernetes is an open-source container orchestration system that facilitates the deployment, management, and scaling of containerized applications.
Using Kubernetes offers many benefits, such as fault tolerance, easier deployments, and management and scaling of containerized applications.&lt;/p&gt;
</content>
        
    </entry>
</feed>
