Docker: Running Apps Everywhere

Docker: Running Apps Everywhere

Introduction to the Docker world

What is Docker?

Docker is a platform that allows developers to easily create, deploy and run applications inside containers.

What are containers?
Containers can be understood as lightweight virtual machines, but they are much faster and less demanding than them, they contain everything needed to run an application: code, libraries and operating system settings.

docker image

Why use Docker?

  1. Application operation on different systems

    When an application runs in a container, it can run anywhere, either locally or in a remote server. Containers allow applications to work consistently in different environments, and this is particularly noticeable in teams that develop applications on different computers using different operating systems, such as:

    • Developer A (Windows): Develops an application in a Docker container.
    • Developer B (Mac): Testing the application in a Docker container.
    • Production server (Linux): Runs the application in the same Docker container.

    Without Docker, every developer would have to install all the necessary tools and libraries on their computer, which can lead to compatibility and reproducibility issues. And if Docker is used, then all developers use the same Docker image, which allows them to develop and test the application in an identical environment. Finally, the application is transferred to production without worrying about different versions of libraries or software on the production server.

  2. Application Isolation

    Containers allow each application to run in its own separate environment, without interfering with each other. This can be very important for companies that develop or host two different applications that require different versions of the MySQL database. In that case it is ideal to use Docker because then each application can be placed in its own Docker container with the appropriate version of MySQL, as in the following example:

    • Application 1 (MySQL 5.7): Running in a Docker container with MySQL 5.7
    • Application 2 (MySQL 8.0): Running in a Docker container with MySQL 8.0

    Or when the team is working on an application that depends on specific versions of Node.js, NPM or some other libraries. In that case, when Docker is used, the team creates a Docker image that contains all the necessary dependencies, so the application is launched in exactly the same environment, without worrying about library versions.

  3. Application scalability

    Docker allows easy scaling of applications horizontally (adding new instances), so if a company experiences a sudden increase in traffic on its e-commerce platform, then the system is easily scaled by adding additional containers to handle a larger load, such as:

    • Web servers: 10 Docker containers with Nginx
    • API servers: 15 Docker containers with the application
    • Web servers: 15 Docker containers with MySQL

Basic Docker concepts:

  • Docker Image: Template for creating containers. Defines what the container will look like.
  • Docker Container (Container): Running instance of Docker image.
  • Dockerfile: File with instructions on how to create a Docker image.
  • Docker Hub: Repository for sharing and downloading Docker images.

Installing Docker

Here is a quick installation guide:

  1. Checking system requirements:

    • Docker Desktop requires 64-bit Windows 10 or later with version 21H2 or later, or Windows 11.
    • Virtualization must be enabled in BIOS (Hyper-V and Windows Container features).
    • Installation requires at least 4GB of RAM.
  2. Download the Docker Desktop installer: at this link or visit the installation page and click the “Download Docker Desktop for Windows” button.
  3. Run the installer (eg “Docker Desktop Installer.exe”) and follow the on-screen instructions.
  4. Restart your computer
  5. Check Docker installation:

    • Open a terminal (PowerShell or Command Prompt) and run the command:
    • If you see the Docker version, it means that the installation was successful.

NOTE:
The installation procedure may change from version to version, so it is best to check the current status on the official page.

Using Docker

Docker can be used through the downloaded Docker Desktop application or through the terminal, here are some of the most common terminal commands:

  1. Downloading Docker image from Docker Hub

    Such as:

    or

  2. Creating the image according to the instructions from the Dockerfile

    In the current directory:

    If the DockerFile is in a different location:

    Where is:

    • -t: Tags the image with a name.
    • -f: Specifies the path to the Dockerfile.
  3. Showing available Docker images

    The docker images command is used to display a list of all Docker images currently stored on your local machine.

    When using only docker images with no additional options, Docker only displays the latest tagged images for each repository. This means that if you have multiple versions of an image with different tags, only the latest version is displayed. When you add the “-a” or “–all” option, Docker displays all images, including all versions of the same image as the so-called “dangling images” ie. images that have no tags and are often the result of intermediate steps during the image building process.

    Example

    This option allows us to see all the images stored on your system, helping you manage disk space and decide which images to delete.

  4. Starting the container

    Such as:

    or with additional options:

    Meaning of options:

    • -d: Runs the container in the background (detached mode)
    • -p: Maps host:container ports (eg 8080:80)
    • –name: Assigns the name “my-nginx” to the container
  5. List of running containers

    Eg.

    or with additional options:

    The a option shows all containers, including stopped ones.

  6. Stopping a running container

    Stop by name:

    or by id:

  7. Deleting the container

    Delete by name:

    NOTE:
    The command "docker container prune" removes all stopped containers from your system. This command helps free up space and maintain a tidy Docker environment by removing containers that are no longer active.

  8. Deleting the Docker image

    Eg:

    NOTE:
    “Dangling” images are those that are not associated with any repository or tag. They usually have “none” as the repository name and tags. The command "docker image prune" is used to remove unused (dangling)Docker image from your local system.

  9. Executing a command inside a running container:

    Eg:

  10. Displaying container logs:

    Eg. showing all logs

    Displaying the last 10 lines of the logo:

Docker Volume

Docker volume is a mechanism for persistent storage of data generated and used by Docker containers. Volumes allow data to survive container restarts, and can be shared between different containers. They are used to manage data in a way that is independent of the container’s lifecycle.

Key features of Docker volumes:
  • Data Persistence: Data stored in Docker volumes persists even when the containers using them are deleted.
  • Data sharing: Multiple containers can use the same volume at the same time, which allows data sharing between containers.
  • Data isolation: Docker volumes are isolated from the host system (host) and other containers, which contributes to better security and data organization.
  • Performance: Docker volumes typically offer better performance compared to storing data directly on the container’s file system.

Creating and using Docker volumes:

Creating volumes:

View of existing volumes:

Container volume usage:

When you create or run a container, you can mount the volume using the -v or --mount option.

Using the -v option:

In this example:

  • my_volume is the name of the volume you are mounting.
  • /app/data is the directory inside the container where the volume will be mounted.
  • my_image is the Docker image you use to create the container.

Using the --mount option:

This syntax is similar, but provides more flexibility and readability.

Managing Docker volumes:

Delete volume:

docker volume rm my_volume

Automatic volume deletion:

When you want to remove all dangling volumes, use the command:

Example of use:

Suppose you have an application that stores data in the /app/data directory inside a container. You want to ensure that this data is persistent and available even if you restart the container.

1. Create a Docker volume:

2. Start the container and mount the volume:

Data created in /app/data inside container my_app_container will be stored in volume app_data, which you can use with other containers or access directly if needed.

Docker Compose

Docker Compose is a tool that makes it easy to manage multi-container Docker applications. Using simple YAML file (docker-compose.yml), we can define the configuration of all the services, networks and volumes that make up our application, and then start and manage them with a single command. Docker Compose is included as part of the Docker Desktop installation.

YAML (YAML Ain’t Markup Language):

YAML is a data serialization format designed to be easy to read and write. Data is organized into key-value pairs. The key and value are separated by a colon and a space. The data structure in YAML is defined using indentation with spaces, which allows for a clear hierarchy of data.

Dictionaries are defined using keys and values, with indentation showing which keys belong to which dictionary.

Lists are represented by dashes with a single space in front of each list element.

Comments in YAML start with # and can be placed anywhere in the line.

Example

This example shows a docker-compose.yml instruction file for an application with two services: frontend (Vue.js application) and backend (NestJS API):

Where the backend service (NestJS API) is described in DockerFile:

And the frontend service (Vue.js application) described in DockerFile:

Explanation of steps
  • FROM node:18:

    Uses the official Node.js version 18 image as the basis for creating a new container.

  • WORKDIR /app:

    Sets the working directory to /app. If the directory set with WORKDIR does not exist, Docker automatically creates it.

    • The following commands in the Dockerfile will be executed relative to this directory.
    • For example, if the command COPY . . follows after WORKDIR /app, all files will be copied to /app. COPY, ADD, and other commands that take a file or directory as an argument rely on relative paths to the current working directory.
  • COPY package*.json ./:

    Copies package.json and package-lock.json from the current directory on the host to the current working directory inside the container (/app).

    • ./ points to the working directory (set with WORKDIR).
  • RUN npm install:

    Runs npm install inside the current working directory (/app).

    • Installs all Node.js dependencies according to package.json.
  • COPY . .:

    Copies all remaining code from the current directory on the host to the current working directory inside the container (/app).

  • CMD [“npm”, “start”]:

    Sets up a command line to start the application using npm start.

Project structure:

To start the application, it is necessary to “switch” to the location of the project in the terminal:

And then we run Docker Compose as follows:

After which we can view the application in the browser: