Skip to content

Docker: Dockerfile

Rayan edited this page Mar 20, 2024 · 15 revisions

Dockerfile

A Dockerfile is a set of instructions for creating Docker images, which are self-contained packages enabling easy deployment and execution of applications in consistent environments.

Definition

A Dockerfile is a set of instructions for creating Docker images, which are self-contained packages enabling easy deployment and execution of applications in consistent environments.

This short sentence describes Dockerfiles pretty well. However there is more to it. A Dockerfile is a plain text file that serves like a blueprint for building a Docker image. It contains series of instructions, each representing a discrete action. For this, instructions are used, like CMD. CMD instructs the Dockerfile to execute a default command automatically when the line is read and executed. This command defines the primary process that runs within the container. All these instructions are executed by the Docker daemon. This allows the encapsulation of an application or service with the goal being, to generate a reproducible and self-contained image.

Instructions

As mentioned, before the Dockerfile contains a series of instructions. These instructions allow the Docker daemon to execute certain tasks/commands and access files. I've only mentioned one instruction so far, that being CMD, which allows the Docker daemon to execute default commands. There are many more and I will list some of them here:

  1. FROM: Specifies the base image to use for the Docker build, for example portainer. Every Dockerfile must start with a FROM instruction, this FROM instruction indicates the start for the image build process.

  2. RUN: Executes commands inside the Docker image during the build process. It's commonly used for installing packages, setting up dependencies, and performing other build-time tasks.

  3. COPY / ADD: Copies files and directories from the host machine into the Docker image. COPY is preferred for copying local files, while ADD can handle URLs and automatically unpack compressed files.

  4. WORKDIR: Sets the working directory inside the Docker image where subsequent instructions will be executed. It's similar to the cd command in shell scripts.

  5. CMD: Specifies the default command to run when a container is started from the image. It defines the primary process for the container. Only the last CMD instruction in a Dockerfile is effective.

  6. EXPOSE: Documents which network ports the container listens on during runtime. It does not actually publish the ports, but it's used to inform users about the intended network ports for the container.

  7. ENV: Sets environment variables inside the Docker image. These variables can be used to configure the behavior of applications running inside the container or to pass runtime configuration.

  8. ENTRYPOINT: Similar to CMD, but it provides a way to configure a container that will run as an executable. The specified command or script is the entry point for the container, and CMD values are treated as arguments to ENTRYPOINT.

  9. VOLUME: Creates a mount point with the specified name and marks it as externally mountable. It's used to allow persistent storage or to share data between containers or between a container and the host system.

Usecases

Using Dockerfiles, as mentioned before, helps encapsulate applications and services, making reproducible self-contained images. This approach finds application in various scenarios across software development and deployment:

  1. Development Environments: Ensures consistency across development machines by defining dependencies and configurations in Dockerfiles.

  2. CI/CD Pipelines: Automates build, test, and deployment processes, ensuring consistent environments from testing to production.

  3. Microservices Architecture: Enables easy management and scaling of individual services with dedicated Dockerfiles for each microservice.

  4. Scalability and Elasticity: Supports dynamic scaling of containers based on demand, optimizing resource utilization.

  5. Isolation and Security: Enhances security by isolating processes within containers, reducing the attack surface.

  6. Hybrid and Multi-Cloud Deployments: Facilitates seamless deployment across diverse environments, including on-premises and multiple clouds.

  7. Packaging and Distribution: Simplifies sharing and deployment of applications through Docker images via registries like Docker Hub.

In essence, Dockerfiles play a crucial role in modern software development and deployment workflows, offering a standardized and efficient way to package, distribute, and run applications in a variety of environments.

Examples

The following Dockerfile will use a base NodeJS image, with the version 18. When a container is created from this image, it will run the Node.js application defined in index.js and listen for incoming connections on port 3000.

FROM node:18

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["node", "index.js"]

Explanation:

  • FROM node:18: Specifies the base image as Node.js version 18.
  • WORKDIR /usr/src/app: Sets the working directory inside the container.
  • COPY package*.json ./: Copies package.json and package-lock.json from the host into the container's working directory.
  • RUN npm install: Installs application dependencies based on the package.json.
  • COPY . .: Copies the rest of the application code into the container's working directory.
  • EXPOSE 3000: Documents that the container listens on port 3000 at runtime.
  • CMD ["node", "index.js"]: Specifies the command to run the application when the container starts.

This Dockerfile defines a Docker image that packages a Node.js application. When a container is created from this image, it will run the Node.js application defined in index.js and listen for incoming connections on port 3000.

Basic setup: Docker container over Dockerfile

Let's create a basic docker container over a Dockerfile. The idea behind this test is to deploy a base ubuntu image with apache2 directly installed over the Dockerfile.

For this we firstly need to create a folder, let's name it apache server.

mkdir apache-server

With this command a folder/directory called apache-server is created in your current working directory.

After having created the folder we now want to create a file in that folder, that file will be the Dockerfile, this can be achieved by executing the following commands:

cd apache-server
nano Dockerfile

In this Dockerfile you want to copy/paste the following instruction set:

FROM ubuntu 
RUN apt update 
RUN apt install –y apache2 
RUN apt install –y apache2-utils 
RUN apt clean 
EXPOSE 80
CMD [“apache2ctl”, “-D”, “FOREGROUND”]

You can then press CTRL+X then Y and save the file, after that you just want to build the image this can be done with the following command:

docker build -t apache_image:1.0 .

After running this command successfully you should get the following output:

[+] Building 78.4s (6/6) FINISHED                                                                                                                 docker:default
 => [internal] load .dockerignore                                                                                                                           0.0s
 => => transferring context: 2B                                                                                                                             0.0s
 => [internal] load build definition from Dockerfile                                                                                                        0.0s
 => => transferring dockerfile: 175B                                                                                                                        0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                                                            3.6s
 => CACHED [1/2] FROM docker.io/library/ubuntu@sha256:77906da86b60585ce12215807090eb327e7386c8fafb5402369e421f44eff17e                                      0.0s
 => [2/2] RUN apt update && apt install -y apache2 apache2-utils && apt clean                                                                              73.8s
 => exporting to image                                                                                                                                      1.0s
 => => exporting layers                                                                                                                                     0.9s
 => => writing image sha256:c071b58a96be0088bc83cb7b0ae59f26d0fd75393e7ea806d0b26840babe5411                                                                0.0s
 => => naming to docker.io/library/apache_image:1.0                                                                                                         0.0s

After this you have crafted your own docker image. You can see all docker images you currently have on your computer by executing the following command:

docker images

In my case the output would look something like this:

REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
apache_image          1.0       c071b58a96be   40 seconds ago   235MB
portainer/portainer   latest    5f11582196a4   16 months ago    287MB

To run the docker container from the image execute following command:

docker run --name myapache -d -p 80:80 apache_image:1.0

The output should look something like this:

09386d0f293700b6d3d478a089ab6bf216a64fccf9c44c1bd96db4ae69ad2318

Check if your container is running by using following command:

docker ps

Output should look something like this:

CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                                        NAMES
09386d0f2937   apache_image:1.0      "apache2ctl -D FOREG…"   6 seconds ago   Up 5 seconds   0.0.0.0:80->80/tcp                           myapache
7e7e2c160949   portainer/portainer   "/portainer"             13 days ago     Up 26 hours    8000/tcp, 9443/tcp, 0.0.0.0:9000->9000/tcp   portainer

To check if the Apache2 service is actually running you can just type in localhost in your URL-Bar and it should give you back the default Apache2 webpage:

image