X
Popular Searches

How to Add a Volume to an Existing Docker Container

While Docker is a useful tool for packaging and managing applications, it also presents many unique challenges, such as dealing with stored data. Usually, you add volumes to containers in the creation script, but what if you need to make new ones?

Adding a Volume To a Running Docker Container

Unfortunately it’s not as simple as just adding a new volume. Containers must have their volumes configured on startup, which means to add a new volume, you must restart the container. While there is a hacky solution (more on that below), it’s highly recommended that a container restart should be done anyway.

This is for a few reasons. Restarting the container is fairly easy, and most code updates require a restart of the service anyway. Having updates tracked in Git is another big factor, especially if you’re using Docker Compose, and editing the launch script is far better than manually adding the volume to a running container.

If your service is big enough that you are concerned about a few minutes (at most) of potential scheduled downtime to restart the container, you should probably be running a scaling deployment with multiple instances that can be updated independently. Modern auto-scaling systems should be designed to handle that, as code deployments happen often.

If you want to add a volume, you’ll need to stop the running container:

 docker stop my_container

Create a new volume if you need to:

docker volume create nginx-config
Advertisement

And then run it with an updated launch command, adding the --mount flag to configure the source volume and target destination.

docker run -d \
  --name devtest \
  --mount source=nginx-config,target=/etc/nginx \
  nginx:latest

If you’re using Docker Compose, you can automate and track this process more easily, since the volume configuration is handled through a settings file. you’ll need to add the volume to the docker-compose.yml file:

version: "3.0"
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - /docker/nginx-config/:/etc/nginx/

Then, you can restart Docker Compose’s services. Compose has a “restart” command, but it’s actually to just refresh the running service without any config changes. If you want to update the images, you’ll need to run docker-compose up with the --build flag:

docker-compose up -d --build

You can also manually run docker-compose down beforehand to stop the services, but it isn’t necessary in most cases unless you want to run it with the -v flag to destroy existing volumes.

RELATED: What Is Docker Compose, and How Do You Use It?

Cloning From An Existing Container

In almost all cases, you shouldn’t be depending on a container’s current running state. Anything that you care about, such as application data, should be stored in a volume so that it can be persisted across container restarts and rebuilds.

This method probably isn’t a good idea for most people, as it requires you to make a new image every time you want to do this, and it still requires downtime. But, if you do need to add a volume to a running container, you can use docker commit to make a new image based on that container, and then clone it with the new volume.

Grab the container ID from docker ps:

docker ps

And then, clone it with commit:

docker commit f88f33c918d2 imagename
Advertisement

Then, you can run the new image, replacing the old image with the cloned one.

docker run -d \
  --name devtest \
  --mount source=nginx-config,target=/etc/nginx \
  imagename

The Hacky Solution

Docker volumes are really just trickery that the Docker runtime uses to expose host directories to containers, and it all depends on configuration. Because of this, you can actually modify that configuration directly, and restart the entire Docker daemon for your system to apply those changes without restarting at all.

Of course, this is far more complicated than just dealing with a container restart, so if you can manage a minute of downtime, we highly recommend doing that instead.

You’ll need to navigate to Docker’s storage directory:

cd /var/lib/docker/containers

In here will be many folders cooresponding to Docker container IDs, which you can find with docker ps. Open up the one for the container you want to modify.

The config file is config.v2.json, but it’s in a compact format and hard to edit. You can install jq to pretty-print JSON on the command line, and pipe this to a new file for editing:

jq . config.v2.json > tmp.json

You’ll need to scroll down to find “MountPoints,” which contains the configuration for all the volumes and bind mounts. You can add a new one here, which should be in the following format:

  "MountPoints": {
    "/home/container": {
      "Source": "/var/lib/pterodactyl/volumes/c7fb3a04-e540-48a7-9704-13987f52e933",
      "Destination": "/home/container",
      "RW": true,
      "Name": "",
      "Driver": "",
      "Type": "bind",
      "Propagation": "rprivate",
      "Spec": {
        "Type": "bind",
        "Source": "/var/lib/pterodactyl/volumes/c7fb3a04-e540-48a7-9704-13987f52e933",
        "Target": "/home/container"
      },
      "SkipMountpointCreation": true
    }
  },
Advertisement

Then, once it’s done, you can minify the JSON again back into the config file:

jq -c . tmp.json > config.v2.json

jq is a powerful utility, so if you wanted to automate this process entirely, you could do that.

RELATED: How to Work With JSON On the Command Line

Then, simply restart the Docker service to apply the changes:

sudo service docker restart
Anthony Heddings Anthony Heddings
Anthony Heddings is the resident cloud engineer for LifeSavvy Media, a technical writer, programmer, and an expert at Amazon's AWS platform. He's written hundreds of articles for How-To Geek and CloudSavvy IT that have been read millions of times. Read Full Bio »

The above article may contain affiliate links, which help support CloudSavvy IT.