Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recommended way to provide configuration files to Docker containers

I am moving our web application to docker-compose deployment (Django, DRF, AngularJS).

Docker looks solid now and things are going well.

I want to:

  • confirm with you that I am following best practices regarding application configuration files
  • know if "volume files" are actually bind mounts, which are not recommended

I've managed to use environment variables and docker-compose secrets read from the Django settings.py file and it works. The downside is that environment variables are limited to simple strings and can pose some escape challenges when sending Python lists, dictionaries etc. We also have to define and maintain a lot of environment variables since our web app is installed in many place and it's highly configurable.

On frontend side (AngularJS) we have two constants.js files and the nginx conf. I've used a CMD ["/start.sh"] in Dockerfile and have some sed commands. But this looks really hackish and it also means that we have to define and maintain quite a few environment variables.

  1. Are Docker volumes a good idea to use for these configuration files?

  2. Does such thing as "volume file" actually exist (mentioned here) or is it actually a bind mount? And bind mounts are less recommendable since they depend on the file system and file path on the host.

Volumes documentation briefly mentions files: "path where the file or directory are mounted in the container", but does not go into greater detail.

Our web app has simple configuration files now:

  • settings.py
  • site\contants.js
  • admin\constants.js

and:

  1. I want to avoid moving those files to dedicated directories that can be mounted.

  2. Can you show me a sample docker-compose.yml with single file volumes (not bind mounts).

Thank you

like image 323
waverider Avatar asked Apr 14 '20 07:04

waverider


People also ask

Where should I put Docker config?

In Windows containers, configs are all mounted into C:\ProgramData\Docker\configs and symbolic links are created to the desired location, which defaults to C:\<config-name> . You can set the ownership ( uid and gid ) for the config, using either the numerical ID or the name of the user or group.

Which configuration files can be used to build Docker workflow?

yml when building a multi-container Docker application. The docker-compose. yml file lets you define a set of related services to be deployed as a composed application with deployment commands. It also configures its dependency relations and runtime configuration.


1 Answers

If you can't use environment variables then you should use a bind mount. If you use a named volume you can't access single files and you can't directly edit the config files.

A named volume is always an entire directory, and can't be directly accessed from the host. There is no such thing as a "volume file" (your linked question is entirely about bind mounts, some using named-volume syntax) and there is no way to mount a single file out of a named volume.

Newer Docker has a couple of different syntaxes for bind mounts (in Compose, the short and long volumes: service configuration, or creating a type: bind named volume). These are all basically equivalent, and many of the answers in the question you link to involve making a named volume simulate a bind mount.

Docker Compose supports relative paths, so there is much less of a concern around host paths for bind mounts being non-portable across systems. A basic fragment of a docker-compose.yml file could include:

services:
  app:
    build: django
    volumes:
      - ./config/django-settings.py:/app/settings.py

In this example I'd suggest a (deploy-time) config directory that contains the configuration files, but that's an arbitrary choice; if you want to bind-mount ./django/settings.py from the application source tree over what's in the image to be able to directly edit it, that's a valid choice too. You can check this tree into source control, and it will still work regardless of where it's checked out.

If you're using a base image with the full GNU tool set (Ubuntu, not Alpine) then your container entrypoint script can also use envsubst as a very lightweight templating tool (it replaces $VARIABLE references with the equivalent environment variable), which will help you support the "many options" case but not the "dict-type options" case.

In general I'd recommend bind mounts for two cases and maybe a third: for config files (where the operator needs to directly edit them), for log files (where the operator needs to directly read them) and maybe for persistent data storage (where your existing backup solution will work unmodified; but not on MacOS where it's very slow). Named volumes can be a good match for the persistent-data case and better match what you would use in a clustered environment (Swarm, Kubernetes) but can't be directly accessed.

like image 52
David Maze Avatar answered Nov 03 '22 18:11

David Maze