Part 2: Volume Mounts and Editing Code
Having an image from which you can work is only the first step to being productive. You need to write code, edit code, and debug code. You have build tools such as gulp or grunt to run. You need Babel for ES6 and beyond, Browserify or WebPack for front-end development, JSHint for code linting, etc. And you need to do all of this in a Docker container while still being able to use your favorite code editor and debugger on your local system.
The core feature of Docker that allows for this to happen is a data volume. As you’ll see in the next few recipes, there are two basic types of data volumes: host mounted volumes, and Docker’s own data volumes (which can be named for easier reference).
Host mounted volumes allow you to share files from your local system, with a Docker container. This means you can edit code locally, and have the changes immediately reflected in a container.
A Docker data volume, on the other hand, is hidden away in Docker’s internals. It allows you to optimize file system performance, provides persistent storage for otherwise transient and temporal container instances, and even lets you share data between containers.
Recipe 4: Editing Code with Volume Mounts
With your core Docker images created and your code up and running, it’s time to think about editing within the container.
However, a Docker image is immutable - meaning once the image is created, it can’t be changed. Additionally, changes made directly inside of a Docker container (an instance created from an image), will be reverted back to the image version, when the container is shut down.
So, how do you edit code in a Docker container if you can’t change or save anything?
Host mounted volumes.
These allow you to specify a folder from your host operating system and mount it directly inside of a container, at a path you specify. By mounting your project’s code folder into your docker container, you can edit the code directly on your host operating system (with your favorite editor!) and the changes will be immediately reflected in the Docker container.
The Recipe
This recipe will modify the way in which you docker run a container instance, adding a -v flag to specify a host mounted volume.
docker run -v /my/local/folder:/var/app # ...
Cooking Instructions
When using the -v option with docker run, you need to specify a full path to the current folder on the left-hand side of the local:remote value for the flag.
The local path must start with a /. If it does not begin with a /, then Docker treats this as a named volume and not a host mounted volume (see Recipe 6 for more info on that).
The remote path should be the correct folder where you code lives. In this case, it will be the /var/app folder that was created in the Dockerfile. This is where the code for the application is copied during the image build.
Specifying a -v flag with a remote destination of the /var/app folder will tell Docker to use your local host folder instead of the folder contained in the Docker image.
Example Local Folder Specifications
On a macOS host, you can specify a local folder such as /Users/derick/dev/docker-recipes/recipe-4/ on the left-hand side of the -v flag value. Note that you cannot use the ~/ shortcut as the path must start with /.
Linux machines will be similar to macOS, though the Users folder will differ slightly in name. For example, on an Ubuntu Linux machine, the folder would be /home/derick/...
On Windows machines, you have to specify the drive letter using the //c/... format. For example, if you have a folder at c:\dev\docker-recipes\recipe-4, you would specify //c/dev/docker-recipes/recipe-4 for the volume mount.
Expanded Environment Variables
It’s often difficult to get the path to your current project correct, when creating host mounted volumes. With long path names, the chance for mistakes increases greatly.
Fortunately, you can use environment variable to expand the current folder (or “process working directory”) into the -v value.
On a macOs or Linux machine, use the $PWD variable in place of the volume location.
docker run -v $PWD:/var/app/ # ...
In a Windows command shell, use %CD%.
docker run -v %CD%:/var/app/ # ...
Or in a Windows PowerShell environment, use ${PWD}
docker run -v ${PWD}:/var/app/ # ...
Bring Your Own Editor
With the -v flag set correctly and your code mounted from the host environment into the Docker container, you can now edit your code with your own editor.
This is great news! You will not be limited to using text-based editors within a Docker container. Instead, you can use any editor installed on your host computer.
Whether that is Visual Studio, VS Code, vim, emacs, Webstorm, Eclipse, or anything else, you will have complete control and freedom in choosing an editor.
What’s Next?
Editing code is only part of the picture for development. You’ll find, over time, that you need to install new and updated npm modules and other runtime dependencies. This can be problematic with Docker and host mounted volumes, as they tend to be rather slow in performance on Windows and macOS.
Coming up next, you’ll see how to correct for this using Docker’s volume instructions.