Series on Docker in Practice & Production - Dockerfile to create an image

Series on Docker in Practice & Production - Dockerfile to create an image

Daily short news for you
  • Privacy Guides is a non-profit project aimed at providing users with insights into privacy rights, while also recommending best practices or tools to help reclaim privacy in the world of the Internet.

    There are many great articles here, and I will take the example of three concepts that are often confused or misrepresented: Privacy, Security, and Anonymity. While many people who oppose privacy argue that a person does not need privacy if they have 'nothing to hide.' 'This is a dangerous misconception, as it creates the impression that those who demand privacy must be deviant, criminal, or wrongdoers.' - Why Privacy Matters.

    » Read more
  • There is a wonderful place to learn, or if you're stuck in the thought that there's nothing left to learn, then the comments over at Hacker News are just for you.

    Y Combinator - the company behind Hacker News focuses on venture capital investments for startups in Silicon Valley, so it’s no surprise that there are many brilliant minds commenting here. But their casual discussions provide us with keywords that can open up many new insights.

    Don't believe it? Just scroll a bit, click on a post that matches your interests, check out the comments, and don’t forget to grab a cup of coffee next to you ☕️

    » Read more
  • Just got played by my buddy Turso. The server suddenly crashed, and checking the logs revealed a lot of errors:

    Operation was blocked LibsqlError: PROXY_ERROR: error executing a request on the primary

    Suspicious, I went to the Turso admin panel and saw the statistics showing that I had executed over 500 million write commands!? At that moment, I was like, "What the heck? Am I being DDoSed? But there's no way I could have written 500 million."

    Turso offers users free monthly limits of 1 billion read requests and 25 million write requests, yet I had written over 500 million. Does that seem unreasonable to everyone? 😆. But the server was down, and should I really spend money to get it back online? Roughly calculating, 500M would cost about $500.

    After that, I went to the Discord channel seeking help, and very quickly someone came in to assist me, and just a few minutes later they informed me that the error was on their side and had restored the service for me. Truly, in the midst of misfortune, there’s good fortune; what I love most about this service is the quick support like this 🙏

    » Read more

Image

As mentioned in the previous article, an image is a file used to create a container. It is also the file that needs to be built in order to run your application. To build an image, you use the following command:

docker build -t <image> <path>
  • -t is the flag used to tag the image.
  • path is the path to the directory containing the Dockerfile.

The name of the image usually consists of three parts: registry/name:tag.

Where registry is the resource to pull/push the image, name is the name of the image, and tag is usually a version. If the registry is not specified, Docker will pull from docker hub. If the tag is not specified, Docker will use the default tag "latest".

To pull an image, you use the docker pull command. To push an image, you use the docker push command. To tag an image that already exists in your machine, you use the docker tag command. To view the list of images in your machine, you use the docker image ls command. For example:

# pull nginx image version 2.1
docker pull nginx:2.1

# push nginx to the estacks registry
docker tag nginx:2.1 registry.estacks.icu/nginx:2.1
docker push registry.estacks.icu/nginx:2.1

# view the list of images in your machine
docker image ls

Refer to the docker build, docker image documentation for more commands.

Dockerfile

Most of the images we create are based on another image, usually starting with:

FROM node:12

Applications written or used on any platform usually have base images available on the Docker Hub. For example, for node.js, there is node, and for MySQL, there is mysql...

Docker Hub acts as a registry, and ordinary users can also upload their images to it. There is a way to identify official images (i.e., images provided by the official provider) by the prefix _ in their URLs.

You can also create your own base images if you have a good reason to do so (!?).

In summary, the idea to build an image that can run your app is to base it on a suitable base image for the platform your app is using.

Basic Dockerfile commands

FROM

FROM is the instruction to build an image from a base image. A Dockerfile must start with the FROM command, followed by the name of the image. The image name can be any valid name that Docker can pull from a registry or is available on the host.

For example:

FROM node:12

Refer to FROM for more information.

COPY

COPY is the command used to copy files/folders from the local system to the image. You usually need this command because your source code needs to be copied into the image in order to run it.

COPY <src> <dest>

## Example: copy the directory /User/hoaitx/src/my-app to the /src/my-app directory in the image
COPY /User/hoaitx/src/my-app /src/my-app

dest must be an absolute path, or if WORKDIR is specified, a relative path can be used.

WORKDIR /src

COPY /User/hoaitx/src/my-app my-app

Refer to COPY for more information.

WORKDIR

WORKDIR sets the working directory for any RUN, CMD, ENTRYPOINT, COPY, and ADD commands.

This means that setting WORKDIR to a directory will change the current directory for subsequent commands.

WORKDIR /src

RUN pwd

The result will be /src.

Refer to WORKDIR for more information.

VOLUME

VOLUME is the command to set up a mount point between the Docker host and the container.

When a container is created and runs successfully, any data it creates or stores will be inside the container. When the container is destroyed, all of that data will be lost.

Consider starting a MySQL container. If you accidentally destroy the container, all data will be lost. In this case, you can use VOLUME to map the data folder inside the container to a folder on the local system.

For example, for MySQL, the folder containing the data is /data. Before starting the container, map it to the /User/hoaitx/mysql/data directory on the local system.

VOLUME /User/hoaitx/mysql/data /data

Now, even if you destroy or restart the container, the data will still be safe in that local directory.

Refer to VOLUME for more information.

EXPOSE

EXPOSE is used to document which port the application in your image actually listens on, as opposed to leaving it to the user to guess. It helps in exposing a port when running the container.

# Assuming my-nginx app is configured to run on port 8080
EXPOSE 8080

In this case, I know that I need to map port 8080 to port 8081 on my Docker host:

docker run --name my-nginx -p 8081:8080 my-nginx

Refer to EXPOSE for more information.

ENTRYPOINT

ENTRYPOINT allows you to configure a command that will always be executed when starting a container.

ENTRYPOINT ["executable", "param1", "param2"]

Where executable is a command or a binary, such as bash or node...

For example, to run my Node.js application, I need to execute the node server.js command every time the container is started:

ENTRYPOINT ["node", "server.js"]

Refer to ENTRYPOINT for more information.

CMD

CMD provides default values for the command and parameters to be executed when running a container. In a Dockerfile, if there are multiple CMD instructions, the last one is used.

CMD ["executable", "param1", "param2"]

For example, when starting a container, I need to run the node server.js command to start the server:

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

Refer to CMD for more information.

So, if you have noticed, ENTRYPOINT and CMD seem to be similar in usage. Both are executed every time a container is created. They both have an executable and parameters.
The difference lies in the purpose of each command. "CMD provides default values," which means CMD may not have an executable, in which case ENTRYPOINT is required to specify the executable. On the other hand, ENTRYPOINT always requires an executable. Combining ENTRYPOINT and CMD creates an image that suits your purpose.

For example, to create an image specifically for a particular command, you would use ENTRYPOINT. Conversely, if you want to create a generic image, you can use CMD.

Apart from the basic commands I explained above, there are more commands you can refer to in the documentation.

Let's create our first image

Now, let's apply everything I shared above to analyze what I did in this Dockerfile :D

FROM node:12

ENV NODE_ENV=production

WORKDIR /app

COPY ["package.json", "package-lock.json*", "./"]

RUN npm install --production

COPY . .  

EXPOSE 3000

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

Build:

docker build -t registry.estacks.icu/my-node:1.0.0 .  

Run:

docker run -d -p 3000:3000 my-node:1.0.0

Summary

Most of the time, we create images based on another image. Images created with a Dockerfile contain instructions on how to build your application. The name of the image usually consists of three elements: <registry>/<name>:<tag>. If <registry> is not specified, Docker will pull from the Docker Hub by default. If <tag> is not specified, Docker will default to "latest".

Premium
Hello

The secret stack of Blog

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click now!

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (1)

Leave a comment...
Avatar
Phan Tung3 years ago
bài viết rất bổ ích, cảm ơn tác giả
Reply
Avatar
Xuân Hoài Tống3 years ago
Cảm ơn bạn, nhớ ghé thăm blog thường xuyên nhé