Introduction to Docker - Part2 (Docker Compose, Docker File, Docker Volume)
Tags: docker, tutorial, openexchange, webdev
Published: 2023-09-16 11:32:23

### Hi Community,

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In my previous article, we learned topics listed below:</span></span></span></span></span></span>

  1. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      What is Docker?
    </div>

  2. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Some of the Docker benefits
    </div>

  3. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      How does Docker work?
    </div>

  4. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Docker Image
    </div>

  5. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Docker Container
    </div>

  6. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Docker Image repository
    </div>

  7. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      InterSystems's Docker image repository
    </div>

  8. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Docker Installation
    </div>

  9. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Docker Basic Commands
    </div>

 10. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Running IRIS community edition by using Docker
    </div>

 11. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Docker Desktop GUI
    </div>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In this article, we will cover the following topics:</span></span></span></span></span></span>

  1. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Use of Docker Compose file (<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">a YAML file)</span></span></span></span></span></span>
    </div>

  2. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      <span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Use of Docker file (employed to build a Docker image)</span></span></span></span></span></span>
    </div>

  3. <div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
      Use of <span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Docker volume</span></span></span></span></span></span>
    </div>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">So let's begin.</span></span></span></span></span></span>

## 1. Use of Docker Compose file (

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">a YAML file)</span></span></span></span></span></span>

[Docker Compose](https://docs.docker.com/compose/) <span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">is a tool developed to help define and share multi-container applications. With Compose, we can create a YAML file to define the services, and with a single command, we can spin everything up or tear it all down.</span></span></span></span></span></span>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">A big advantage of using Compose is the ability to define your application stack in a file and keep it at the root of your project repo. You can also enable somebody else to contribute to your project with ease</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#444746"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">.</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> They would only need to clone your repo and start the compose app. </span></span></span></span></span></span>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In my previous article, we used the command mentioned below to create and start the container with the InterSystems community image:</span></span></span></span></span></span>

<pre class="codeblock-container" idlang="12" lang="Shell Session" tabsize="4"><code class="language-shell hljs">docker run -d -p 52773:52773 intersystemsdc/iris-community </code></pre>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">At this point, let's modify this command and add a container name, map more ports, and set the restart option:</span></span></span></span></span></span>

<pre class="codeblock-container" idlang="12" lang="Shell Session" tabsize="4"><code class="language-shell hljs">docker run -d -p 52773:52773 -p 53773:53773 -p 1972:1972 --name iris --restart=always intersystemsdc/iris-community</code></pre>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j19om9ad8swhnxcr4z5q.png)

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Let me break down the abovementioned command for you:</span></span></span></span></span></span>

<pre class="codeblock-container" idlang="12" lang="Shell Session" tabsize="4"><code class="language-shell hljs"><span class="hljs-meta">#</span><span class="bash">docker run <span class="hljs-built_in">command</span> to create and start the container</span>
docker run 
<span class="hljs-meta">#</span><span class="bash">-d -an option used to start container <span class="hljs-keyword">in</span> deattach mode</span>
-d 
<span class="hljs-meta">#</span><span class="bash">-p -an option is used to map the ports</span>
-p 52773:52773 
-p 53773:53773 
-p 1972:1972 
<span class="hljs-meta">#</span><span class="bash">name of the container</span>
--name iris 
<span class="hljs-meta">#</span><span class="bash"><span class="hljs-built_in">set</span> the restart option to always</span>
--restart=always 
<span class="hljs-meta">#</span><span class="bash">base image</span>
intersystemsdc/iris-community
</code></pre>

## Create the Compose file {#create-the-compose-file}

In the root folder, create a file named `docker-compose.yml a` and write the abovementioned commands as stated below:

<pre class="codeblock-container" idlang="4" lang="YAML" tabsize="4"><code class="language-yaml hljs"><span class="hljs-comment">#specify docker-compose version</span>
<span class="hljs-attr">version:</span> <span class="hljs-string">'3.6'</span>
<span class="hljs-comment">#services/container details</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-comment">#Name of the container</span>
<span class="hljs-attr">  iris:</span>
    <span class="hljs-comment">#Base Image</span>
<span class="hljs-attr">    image:</span> <span class="hljs-string">intersystemsdc/iris-community</span>      
    <span class="hljs-comment">#set restart option</span>
<span class="hljs-attr">    restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-comment">#port mapping</span>
<span class="hljs-attr">    ports:</span>
<span class="hljs-bullet">      -</span> <span class="hljs-number">55036</span><span class="hljs-string">:1972</span>
<span class="hljs-bullet">      -</span> <span class="hljs-number">55037</span><span class="hljs-string">:52773</span>
<span class="hljs-bullet">      -</span> <span class="hljs-number">53773</span><span class="hljs-string">:53773</span></code></pre>

The mapping of the docker run command and a docker-compose file is illustrated below:  

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs7finufcpbqqfq63shq.png) 
A Docker-compose file snapshot is demonstrated beneath:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7mox8j88ee3rrlnl5jwd.png) 

In order to run the docker-compose file code, we will use the docker-compose up command:

<pre class="codeblock-container" idlang="12" lang="Shell Session" tabsize="4"><code class="language-shell hljs">docker-compose up -d</code></pre>

  * `-d` or `--detach`:  an option that runs the command in the background and returns control to the terminal.  


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1z3cqwph90k4k9xhllmf.png)  
The container is started. Let us run "docker ps" command to list down running containers


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oioo90cge3tgbdckip9w.png)

As you can see, we are getting the same result with the docker-compose file.

 

## Create and Start multiple containers

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">With the help of docker-compose not only can we run multiple containers but also organize and add more commands to it.</span></span></span></span></span></span>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">E.g., in the following docker-compose file we are running the MongoDB container along with the iris container:</span></span></span></span></span></span>

<pre class="codeblock-container" idlang="10" lang="XML" tabsize="4"><code class="language-xml hljs">#specify docker-compose version
version: '3.6'
#services/container details
services:
  #Name of the container
  iris:
    #Base Image
    image: intersystemsdc/iris-community      
    #set restart option
    restart: always
    #port mapping
    ports:
      - 55036:1972
      - 55037:52773
      - 53773:53773
  
  #start MongoDB container
  mongodb:
    image: mongo 
    ports:
    - 27017:27017 </code></pre>

Let us run the docker-compose up command


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1e0crd6wemse4fcef3w.png)  
Both MongoDB and iris containers have been created and started now.

<!--break-->

## 2. The Docker file

  
<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Docker can automatically build images by reading the instructions from a</span></span></span></span></span></span> `Dockerfile`. A `Dockerfile` is a text document that contains all the commands a user could call on the command line to assemble an image. 

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">So, our first question is simple. what is a Dockerfile? It is what Docker uses to build the image itself. The Dockerfile is essentially the build instructions of how to create the image.</span></span></span></span></span></span>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">The advantage of a Dockerfile over simply storing the binary image is that the automatic builds will ensure you have the latest version available. It is a good thing from a security perspective because you want to ensure you are not installing any vulnerable software.</span></span></span></span></span></span>

<h2 data-id="9-docker-basic-commands" data-original-id="false" id="9-docker-basic-commands">
  <br />Common Docker file Commands
</h2>

Below you can find some of the most commonly used docker commands. **Please note all of the docker commands must be in Capital letters.**

###  
<u>FROM </u>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">The first one is the FROM command, which tells what image was based on. This is the multi-layered approach that makes Docker so efficient and powerful. In this instance, the iris-community Docker image was used, which references a Dockerfile once more to automate the build process.</span></span></span></span></span></span>

<pre class="codeblock-container" idlang="6" lang="Dockerfile" tabsize="4"><code class="language-dockerfile hljs"><span class="hljs-keyword">FROM</span> intersystemsdc/iris-community</code></pre>

  
<u><strong>WORKDIR</strong></u>

This command is used to set up a working directory in which we will copy files.  
E.g the undermentioned command will set /opt/irisbuild as a working directory:  

<pre class="codeblock-container" idlang="6" lang="Dockerfile" tabsize="4"><code class="language-dockerfile hljs"><span class="hljs-keyword">WORKDIR</span><span class="bash"> /opt/irisbuild</span></code></pre>

##  

## <u>COPY</u>

The COPY command is as simple as it sounds.  It can copy files to the container.    
Usually, we copy custom configuration files, applications source files, data files, etc.

<pre class="codeblock-container" idlang="6" lang="Dockerfile" tabsize="4"><code class="language-dockerfile hljs"><span class="hljs-comment">#coping Installer.cls to a root of workdir. Don't miss the dot, here.</span>
<span class="hljs-keyword">COPY</span><span class="bash"> Installer.cls .
</span>
<span class="hljs-comment">#copy source files from src folder to src folder in workdir in the docker container.</span>
<span class="hljs-keyword">COPY</span><span class="bash"> src src
</span>
<span class="hljs-comment">#copy source files from data/fhir folder to fhirdata folder in the docker container.</span>
<span class="hljs-keyword">COPY</span><span class="bash"> data/fhir fhirdata</span></code></pre>

 

### <u>ENV</u>

This sets the environment variables, which can be used in the Dockerfile and any scripts it calls.  
The `ENV` instruction defines environment variable `<key>` to the value `<value>`

<pre class="codeblock-container" idlang="6" lang="Dockerfile" tabsize="4"><code class="language-dockerfile hljs"><span class="hljs-keyword">ENV</span> USER_ID <span class="hljs-string">"SYSTEM"</span>
<span class="hljs-keyword">ENV</span> USER_PASSWORD <span class="hljs-string">"MANAGER"</span>
</code></pre>
<
  
<u><strong>RUN</strong></u>

The `RUN` command is used to execute commands during the image-building process.

<pre class="codeblock-container" idlang="6" lang="Dockerfile" tabsize="4"><code class="language-dockerfile hljs"><span class="hljs-comment">#here we give the rights to irisowner user and group which are run IRIS.</span>
<span class="hljs-keyword">RUN</span><span class="bash"> chown <span class="hljs-variable">${ISC_PACKAGE_MGRUSER}</span>:<span class="hljs-variable">${ISC_PACKAGE_IRISGROUP}</span> /opt/irisapp   
</span><span class="hljs-comment">#start IRIS and run script in iris.script file </span>
<span class="hljs-keyword">RUN</span><span class="bash"> iris start IRIS \    
</span>    && iris session IRIS < /tmp/iris.script</code></pre>

 

<u><strong>USER</strong> </u>

By default, containers run as root, which gives them complete control of the host system. As container technology matures, more secure default options may become available. For now, requiring root is dangerous for others and may not be available in all environments. Your image should use the `USER` instruction to specify a **non-root** user for containers to run as. If your software does not create its own user, you can create a user and group in the Dockerfile.

<pre class="codeblock-container" idlang="6" lang="Dockerfile" tabsize="4"><code class="language-dockerfile hljs"><span class="hljs-comment">#here we switch user to a root to create a folder and copy files in docker.</span>
<span class="hljs-keyword">USER</span> root 

<span class="hljs-keyword">WORKDIR</span><span class="bash"> /opt/irisapp
</span>
<span class="hljs-comment">#switching user from root to irisowner, to copy files</span>
<span class="hljs-keyword">USER</span> irisowner 

<span class="hljs-keyword">COPY</span><span class="bash"> src src</span></code></pre>

For more details, please read <a href="https://docs.docker.com/engine/reference/builder/" rel="nofollow"><strong>Docker official documentation</strong></a>

<!--break-->

## 3. Docker Volume

A Docker volume is an independent file system entirely managed by Docker. It exists as a standard file or directory on the host where data persist.

The purpose of using Docker volumes is to keep data outside the container to make it available for backing up or sharing.

Docker volumes depend on Docker’s file system and are the [preferred method](https://docs.docker.com/storage/#good-use-cases-for-volumes) of persisting data for Docker containers and services. When a container is started, Docker loads the read-only image layer, adds a read-write layer on top of the image stack, and mounts volumes onto the container filesystem.

we use `-v` or `--volume` flag to allow ourselves to mount local files into the container.

Volumes are the preferred mechanism for persisting data generated and used by Docker containers. While [bind mounts](https://docs.docker.com/storage/bind-mounts/) are dependent on the directory structure and OS of the host machine, volumes are completely managed by Docker. Volumes have several advantages over bind mounts:

  * Volumes are easier to back up or migrate than bind mounts.
  * You can manage volumes using Docker CLI commands or the Docker API.
  * Volumes work on both Linux and Windows containers.
  * Volumes can be more safely shared among multiple containers.
  * Volume drivers let you store volumes on remote hosts or cloud providers, to encrypt the contents of volumes, or to add other functionality.
  * New volumes can have their content pre-populated by a container.
  * Volumes on Docker Desktop have much higher performance than bind mounts from Mac and Windows hosts.

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="background-color:#ffffff"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In addition, volumes are often a better option than persisting data in a writable layer of the container because a volume does not increase the size of the containers while using it. Also, the contents of the volume exist outside of the lifecycle of a given container.</span></span></span></span></span></span></span>

![Volumes on the Docker host](https://docs.docker.com/storage/images/types-of-mounts-volume.png) 

We can mention volumes under the services section in the docker-compose file.

<pre class="codeblock-container" idlang="4" lang="YAML" tabsize="4"><code class="language-yaml hljs"><span class="hljs-comment">#specify docker-compose version</span>
<span class="hljs-attr">version:</span> <span class="hljs-string">'3.6'</span>
<span class="hljs-comment">#services/container details</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-comment">#Name of the container</span>
<span class="hljs-attr">  iris:</span>
    <span class="hljs-comment">#Base Image</span>
<span class="hljs-attr">    image:</span> <span class="hljs-string">intersystemsdc/iris-community</span>      
    <span class="hljs-comment">#set restart option</span>
<span class="hljs-attr">    restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-comment">#port mapping</span>
<span class="hljs-attr">    ports:</span>
<span class="hljs-bullet">      -</span> <span class="hljs-number">55036</span><span class="hljs-string">:1972</span>
<span class="hljs-bullet">      -</span> <span class="hljs-number">55037</span><span class="hljs-string">:52773</span>
<span class="hljs-bullet">      -</span> <span class="hljs-number">53773</span><span class="hljs-string">:53773</span>
    <span class="hljs-comment">#create a volume</span>
<span class="hljs-attr">    volumes:</span>
<span class="hljs-bullet">      -</span> <span class="hljs-string">./:/irisdev/app</span>  </code></pre>

we have created irisdev/app volume.

##  

<h2 data-id="summary" data-original-id="false" id="summary">
  Summary
</h2>

<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Docker is a powerful tool that allows developers and IT teams to create, deploy, and run applications in a containerized environment. By providing portability, consistency, scalability, resource efficiency, and security, Docker makes it easy to deploy applications across different environments and infrastructures. With the growing popularity of containerization, Docker is becoming an essential tool for modern software development and deployment.</span></span></span></span></span></span>  
<span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial,sans-serif"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In this article, we learned how to use Docker compose (a YAML file that specifies the configuration options for each container in the application), Docker file (employed to build a Docker image) and Docker volume (a persistent data storage mechanism operated to share data between Docker containers and the host machine.)</span></span></span></span></span></span>

 

Thank you for reading!