You can find the Chinese version at Docker 實戰系列:一步一步帶你 dockerize 你的應用.
Imagine this scenario, you have finished developing your application and are ready to deploy it to the remote machine. However, you find the server's distribution is not Ubuntu or CentOS, which you are most familiar with. Moreover, to run the application, you have to first install system dependencies such as Node.js and MongoDB manually. This can be quite a hassle! Now is the perfect moment to use Docker.
Docker can help you pack the Ubuntu + Node14 + MongoDB environment with your JS code into a single image. This way, you can effortlessly run the entire image on the remote server without any concerns about environmental issues.
What is Docker
Docker is a lightweight virtualization technology that can easily package your application and its environment into an image so that you don't have to worry about environmental issues anymore.
The following example demonstrates using Docker to run three separate applications in different containers. Each container provides an independent environment, which means that they can have different systems, databases, compilers, etc. For example, you can run Node 8 in one container and Node 14 in another.
Let's try using Docker
Install Docker
Docker can be run on Linux, macOS, and Windows. You can go to the "Get Docker" page and get the version compatible with your OS. After installing Docker, you can run the command docker run hello-world
to verify Docker is properly installed.
Create a Ubuntu environment using Docker
Docker makes it easy to get the desired environment you want. For example, if you need a Ubuntu Bash environment at the moment, you can first obtain the Ubuntu image from Docker Hub.
docker pull ubuntu
docker image ls
After preparing the Ubuntu image, you can run a Bash process in a Ubuntu container. The -it
option enables interactive mode in the container, which allows us to execute commands in Bash.
docker run -it ubuntu bash
After getting into the container, you can run the command cat /etc/*release
so you can see the Ubuntu version, which is 22.04.2 LTS on my side.
You may be confused Image with Container. You can think of an Image as the code. They are simply files stored on disk and not currently running. A Container, on the other hand, is a running instance of an Image. Containers use your CPU and memory resources to execute the code contained in the Image.
In summary, Docker allows you to get the desired environment. Next, I will tell you how to package your application with the environment you want.
How to Dockerize an existing application
Dockerize means to package an application and environment into a Docker image. Once Docker is installed on the target machine, you can simply run the image to deploy the application.
In this post, I'll demonstrate how to dockerize a Node.js application called simple-express-server. The application is an HTTP server that listens on port 8080 and responds with "Hello World!" when accessed.
Step 0 - Creating a Dockerfile
In order to package the code and environment together into a single image, we need to write down all the packaging steps in Dockerfile. So, let's create an empty Dockerfile first.
simple-express-server
├── Dockerfile <-- HERE
├── README.md
├── index.js
├── node_modules
└── package.json
Step 1 - Find a suitable base image
Docker image is built layer by layer, so we need to find a suitable Base Image on Docker Hub, and then process it into the image we want.
Since the project is written in Node.js, we need to find a Node.js environment on Docker Hub. We can find the official Node image on Docker Hub by searching for "Node.js".
If you want to dockerize an application written in other languages, you can easily find the corresponding image for Python, Golang, etc.
After deciding on the base image, we have to select a version for it. In this case, we're using node:18.15
. If you prefer to use the latest version, you can specify node:latest
.
# Dockerfile
FROM node:18.15
Step 2 - Copy the source code into the image
After setting up the Node.js environment, the next step is to copy all the required source code into the image. To do this, we'll use the COPY
command to copy index.js
and package.json
into the /app
directory within the container.
FROM node:18.15
COPY index.js package.json /app/
Step 3 - Install the dependencies
After we have the environment and source code in the image, we need to cd to the /app
directory and install the dependencies.
First, we use WORKDIR
command to cd to /app
, and then RUN
the command npm install && npm cache clean --force
. The purpose of cleaning the cache is to minimize the size of the resulting image.
If you're writing other languages, you can replace npm install
with the corresponding command, such as pip install
, to install the dependencies.
WORKDIR /app
RUN npm install && npm cache clean --force
Step 4 - Specify the initial command
After preparing the environment, source code, and dependencies, the final step is to execute the program. To do this, we use the CMD
to specify the initial command. Because this Node.js application requires node index.js
to start, we'll write down this command to the Dockerfile.
FROM node:18.15
COPY index.js package.json /app/
WORKDIR /app
RUN npm install && npm cache clean --force
CMD node index.js
Step 5 - Build the image
After completing the Dockerfile, we can use the command docker build -t simple-express-server .
to build the image from the Dockerfile.
Once the building process is complete, you can run docker image ls
to view your image named simple-express-server
. The image contains the Node.js environment, application code, dependencies, and the init command.
Run the image on your laptop
Once the image is prepared, we can start the container by running docker run -p 3000:8080 simple-express-server
. Inside the container, the command executed is node index.js
. The option -p 3000:8080
connects port 3000 on your laptop to port 8080 in the container, so that we can access the API server on 127.0.0.1:3000
.
After the application is dockerized, we can start the API server without having to install Node.js. Docker is all we need!
Run in the background
Since the command previous will block the terminal, you can add a -d
option to run the container in the background. After running the command docker run -d <image>
, you will get the container ID. If you want to view logs of the container, just run docker logs -f <container ID>
.
Summary
This post covers the fundamental concepts of Docker and provides a guide to dockerize an existing Node.js application. If you want to learn more about Docker commands, you can check out the base command and Dockerfile reference.
This is the first post of the Docker series. In the upcoming posts, I will cover topics such as docker-compose, docker swarm, and Kubernetes, Please follow me if you're interested in learning about Docker. Thank you!
Continuing with the next post in this series: Pushing Your Docker Images to Docker Hub: A Step-by-Step Guide.