Start from the NGINX container we created in a previous post

docker run -p 80:80 -d --name websrv nginx:latest

The problem we’re going to solve here is: how do we add a custom webpage for NGINX to display? The container’s filesystem is separate from the host’s.

Create a File in the Container

We can create the file directly in the container. Let’s start a shell in interactive mode in the container

docker exec -it websrv bash

We now navigate to the root folder of the web server. To find the location of the root folder, we take a look at the configuration files. The root folder is specified in /etc/nginx/conf.d/default.conf and it’s /usr/share/nginx/html.

Let’s navigate to the root folder and replace index.html with a simple text file. We need to enter the content of the file from the command line, as the container does not have an editor installed (alternatively, we could install one).

mv index.html index_old.html
echo This is a file inside the container > index.html

Visit localhost in a browser on the host and the new index.html will appear (press the refresh button if the page doesn’t update, as the old page may be cached).

There is a problem with this approach. The file we created will be lost if the container is removed (e.g., to be replaced by a new version of the server). To save the changes, we’d need to commit them to a new image, which is beyond the scope of this post.

Storage Options in Docker

To share data between the host and the container, we create a folder on the host’s filesystem and mount it to the container’s filesystem. There are two types of storage options in Docker:

  • Bind mount: any folder on the host’s filesystem
  • Volume: folder managed by the Docker daemon

Bind Mount

Stop and delete the websrv container.

docker stop websrv
docker rm websrv

Now, create a directory called html inside the home directory and create a simple index.html file in it.

mkdir html
echo This is a file on a bind mount > index.html

We want to mount the html directory to the root directory of the web server inside the container. The -v flag (-v host_directory:container_directory) does that

docker run -p 80:80 -d --name websrv \
–v ~/html:/usr/share/nginx/html \
nginx:latest

The original content of the web server’s root directory is replaced by the content of the mount. Visit localhost from a browser to confirm it worked.

To verify the mount configuration, we can use the inspect command and look for the HostConfig/Binds element in the JSON output.

docker inspect websrv | less

Volume

To show how volumes work, we’re going to repeat the same exercise using a volume instead of a bind mount. As before, stop and remove the existing websrv container, as we’re going to recreate it.

Volumes are managed through the docker volume family of commands. To create a new volume

docker volume create html-volume

To see what directory the volume uses on the host, run the volume inspect command and look for the Mountpoint element in the JSON output

docker volume inspect html-volume

The syntax to use a volume is similar to the case of a bind mount (-v volume:container_directory)

docker run -p 80:80 -d --name websrv \
–v html-volume:/usr/share/nginx/html \
nginx:latest

Differently from bind mounts, the original content of the web server’s root folder is copied into the volume. This happens if the volume is empty, like in this case. If the volume has existing content, that will override the content of the container directory it is mounted to (refer to the documentation).

To remove the volume

docker volume rm html-volume

The command will not remove the volume if it’s used by an existing container. The container will have to be removed first. On the other hand, if the container is removed, the content of the volume is preserved.