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.

application:

Via Docker

--name="application"

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 type
  • source — source path
  • destination — path in the container

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

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

Now you can put all the necessary parameters together and create a container.

It remains only to run it and check that everything works as it should 😉

docker start frontend

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.

I’m frontend developer and I💛 it