Dive into Docker Compose with Node.js
--
Docker Compose has become such a popular tool for creating docker containers. It is good for services that work in isolation and do not require composition from containers, because of the ease of use.
Simplicity is a prerequisite for reliability.
— Edsger W. Dijkstra
I have a regular Node.js application. I wrapped it in a container using Compose — everything worked fine, but I had a question: “Can you do the same without Compose?”
All commands that Compose executes can be done through Docker. Before I parsed every line in the docker-compose.yml in detail, building and running a container was kind of magic for me. Now I want to share this information with you.
When you understand things, there’s no more magic.
— Tim Berners-Lee
Image creation
If you specify image
along with build
, then Compose will name the image created from the Dockerfile in context
.
Command via Docker (run from directory with Dockerfile)
docker build -t application_image .
Container creation
Everything else described in docker-compose.yml is container parameters and they are specified when it is created.
I’ll tell you about each parameter separately.
Container name
application:
Via Docker
--name="application"
Volumes
Containers can create, update, and delete files, but these changes are lost when the container is deleted and they are isolated in that container. Volumes can change this behaviour.
Volumes provide the ability to connect specific paths to the container’s file system to the host computer. If a directory in the container is connected, changes to that directory will also be visible on the host machine. If you connect the same directory after restarting the container, the same files will be displayed.
In older versions of Docker, volumes were connected to the container using the --volume
parameter. The --volume
parameter is now deprecated and --mount
should be used instead. This parameter consists of multiple key-value pairs, separated by commas. The main keys you’ll need are:
type
— mount typesource
— source pathdestination
— path in the container
Application content
During development, when you change the source code of the application, you don’t want to create a new image every time so that your changes are pulled into it. Just for such a situation, a volume that will be linked to the source code directory is suitable.
This type of mount is called bind
. Allows you to specify the exact directory on the host machine.
--mount type=bind,source="$(pwd)",destination=/home/node/app
node_modules
The modules folder is not needed by the host machine when launching the application from the container, but this folder will conflict with the same folder in the container.
To solve this problem, a volume of type volume is usually used. With this type of mount, saving the volume will be controlled by Docker itself and will put it in its directory. Therefore, it does not need to specify the source
key.
--mount type=volume,destination=/home/node/app/node_modules
Container creation
Now you can put all the necessary parameters together and create a container.
Running
It remains only to run it and check that everything works as it should 😉
docker start frontend
Simple commands
I understand that all these commands look cumbersome and at first it is all difficult to remember, so for myself I created a Makefile with which I always have these commands at hand.
Conclusion
Compose is a very cool utility that hides all the routine work of launching and managing a container under the hood. But if you’re like me, and are worried about magical moments in the application, then you should try to create a container without Compose at least once.