Part 3: Debugging In A Container
No matter how well written, and no matter who wrote it, every application goes through the debugging process at some point in time. Even with the most advanced development tools, and techniques that minimize the need for debugging, it is still a required skill for development.
This is true of code you write on your machine directly, and of code written in a Docker container. And, fortunately, there are many options for debugging code in a container.
In the next few chapters, you’ll find the core concepts, configuration and tooling examples that you need, to find and fix bugs in your code, while it runs in a container.
From command-line debugging with Node.js, to editors like Visual Studio Code, the options for working with code in a container are nearly as plentiful as working on your machine, directly.
Recipe 6: Cache npm install for Faster Startup
When working with Docker in production, a container is created from an immutable image. That is, the image itself is a set binary that cannot be changed.
Because of this, having your npm modules installed into your image is a good idea. You can deliver the complete image to your production environment and the application should run as expected - no additional installation or configuration needed.
In a development environment, however, the immutable nature of an image can be a problem. As developers, we need to update modules, install new libraries, and generally modify the contents of the application.
You’ve already seen how you can modify the contents of an application through host mounted data volumes.
However, if you’re in the middle of a development cycle and a new version of your Docker image is made available by your team, this can mean lost times and duplicated time to re-install new and updated versions of libraries that you need.
To solve this, take advantage of another feature in Docker’s data volumes: re-usability through named volumes.
The Recipe
This recipe involves a modification to the command-line options used to run a container in development - no changes needed to the Dockerfile, as in Recipe 5 you already added the needed VOLUME instruction for the /var/app/node_modules folder.
For this to work, you only need to change the way you specify the -v volume mount.
Rather than specifying a full /folder/sub-folder location, use a simple name for your volume without a leading /.
docker run -v my-app-modules:/var/app/node_modules # ...
Cooking Instructions
When you provide a -v volume option to the docker run command, that does not begin with a /, Docker sees it as a volume name. If that name does not exist, then the named volume is created for you. If the name does exist, then it re-uses the existing volume.
Nothing here sounds new or exciting, compared to previously discussed volumes, so far. But there are two secrets to this recipe that make it work.
- Re-using named volumes across container instances
- Docker volumes are never removed or cleaned out, unless you do so manually
Re-using A Named Volume
When you use the same named volume across multiple containers, those containers point their internal folder to the same external drive space. This can be a very bad idea if you have multiple live containers that are accessing the same drive space at the same time (though there can be valid uses for this, too).
When working in a development container, however, you can take advantage of this. When creating a new container instance for your project, specify the same name in the -v option for the node_modules folder, in the docker run command. This will load the existing data volume for your node_modules, meaning Docker will not have to re-install anything. You’ll pick up right where you left off.
Docker Volumes Are Persistent
Docker volumes are never automatically cleaned up or deleted. They will live on a machine until they are manually removed.
This is both a blessing and a curse.
On one hand, this allows you to re-use the same named volume no matter how many times you rebuild or update your base Docker image, Dockerfile or container instance.
On the other hand, it’s very easy to accidentally eat up all of your hard drive space by having too many data volumes from old, deleted container instances.
To solve this problem, you can use the docker volume command and associated options to remove old volumes.
What’s Next?
With your code in working order, and your node_modules folder correctly cached, it’s time to start hacking on your projects. But writing code also means debugging code - a critical part of the development process.
The next part of this book will talk about some of the tricks you need to do debugging in a running Docker container.