August 12, 2017

Mounting Files vs Mounting Directories

We dive into an important difference in behavior when mounting a single file vs whole directories.

To test out the difference between file vs directorying mounting, we'll create an Nginx configuration file on a host file system (Linux) and try out both methods to mount in a server configuration.

Nginx

First I pull the official Nginx image:

docker pull nginx:alpine

cd /opt
sudo mkdir conf.d
sudo vim conf.d/default.conf

We'll make it proxy fideloper.com, as site with no SSL certificate that won't redirect us to a different location. I create file /opt/conf.d/default.conf on a Linux host's local file system:

upstream app {
    server fideloper.com:80;
}

server {
    listen 80 default_server;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    server_name _;

    charset utf-8;

    location / {
        proxy_set_header Host fideloper.com;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://app;
        proxy_redirect off;

        # Handle Web Socket connections
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Start Nginx, mounting that configuration file to where Nginx will be looking for configuration files:

docker run -d \
    --name=nginx \
    -v /opt/conf.d/default.conf:/etc/nginx/conf.d/default.conf \
    -p 80:80 \
    nginx:alpine

It works in the browser, goes to fideloper.com!

Changing the Mounted File

Let's change the conf file. We'll have it proxy direct.shippingdocker.com instead of fideloper.com with the following two changes:

# Upstream
server direct.shippingdocker.com:80;

# Host
proxy_set_header Host direct.shippingdocker.com;

Reload Nginx:

docker kill -s HUP nginx

We'll see in the browser that Nginx is still proxying the fideloper.com site! It didn't suck in the configuration file change.

We can see that the file in the container was not updated:

# On our local system
cat conf.d/default.conf

# In the container
docker exec nginx cat /etc/nginx/conf.d/default.conf

It still proxys fideloper.com!

Nginx did see the reload command, but it didn't see the file being changed.

This is related to Linux, vim, and how it sees file changes (replace vs edit in place): https://github.com/docker/docker/issues/15793#issuecomment-135411504.

The Fix:

Mount directories instead of files!

Let's kill the original Nginx container and start a new one with a directory mounted:

docker stop nginx
docker rm -v nginx

# Mount the directories instead of a file
docker run -d \
    --name=nginx \
    -v /opt/conf.d:/etc/nginx/conf.d \
    -p 80:80 \
    nginx:alpine

It now shows the results of direct.shippingdocker.com!

And we can change it back it to make sure:

# Upstream
server fideloper.com:80;

# Host
proxy_set_header Host fideloper.com;

And reload nginx:

docker kill -s HUP nginx

...and we'll see this now proxying the fideloper.com site - the change was propogated into the container, and reloading Nginx worked.

Looking for a deeper dive into Docker?

Sign up here to get a preview of the Shipping Docker course! Learn how to integrate Docker into your applications and develop a workflow to make using Docker a breeze!

All Topics