docker-compose template
Run it
Execute this template like so:
cookiecutter https://quico.space/Quico/py-cookiecutter-templates.git --directory 'docker-compose'
Cookiecutter interactively prompts you for the following info, here with example answers:
project_slug [dir-name]: grafana
service [grafana]:
component_list [grafana]: grafana,nginx
context [ctx]: cncf
Select build:
1 - no
2 - yes
Choose from 1, 2 [1]:
Done, directory structure and files for your next docker-compose project are ready for you to hit the ground running.
Explanation and terminology
Your four answers translate as follows into rendered files.
-
The
project_slugis used only as directory name. A container namedvaultmay be fine but the project directory namehashicorpvaultmight be more descriptive.. └── hashicorpvault <--- Here ├── build-context │ ├── docker-data │ │ └── .gitkeep │ ├── Dockerfile ... -
The
servicevariable by default copies yourproject_sluganswer. It's a style decision whether you leave it at that and just hitEnter. The service name will come up in rendereddocker-compose.ymlat purely cosmetic locations such as thenetworks:key,container_name:and/opt/docker-datavolume mount presets, here withftpas the service name:services: mysql: image: "mysql:${MYSQL_VERSION}" container_name: "ftp-mysql-${CONTEXT}" <--- networks: ftp-default: <--- ... volumes: # - /opt/docker-data/ftp-mysql-${CONTEXT}/... <--- # - /opt/docker-data/ftp-mysql-${CONTEXT}/... <--- # - /opt/docker-data/ftp-mysql-${CONTEXT}/... <--- ... -
Treat
component_listas the list of Docker images that make up your service. Eachdocker-composeproject forms a service - see above - that consists of either a single or multiple components. They're yourservices:, your container, volume, variable names etc.:services: grafana: <--- image: "grafana:${GRAFANA_VERSION}" <--- container_name: "grafana-grafana-${CONTEXT}" <--- ... environment: # GRAFANA_USER: ${GRAFANA_USER} <--- # GRAFANA_PASSWORD: ${GRAFANA_PASSWORD} <--- ... -
The
contextprompt is a generic string to help you distinguish deployments. It can be whatever you want such as for example a team name, herecncfwhich shows up as a preset in an example env file. It defaults toctxjust so it can't be empty.. └── grafana ... └── env └── fqdn_context.env.example <---Which then looks like:
CONTEXT=cncf ... -
Prompt
buildis a yes-no question. Cookiecutter will create aREADME.mdfile with copy-pastable Docker Compose commands pre-filled. If you answeryesto this promptREADME.mdwill contain an example paragraph that explains the build process along the lines of:docker compose ... --profile 'build' buildWhereas by answering
no(or just hitting<Enter>to accept the default ofno) no such paragraph will be added to the example Markdown file. Build instructions are only really needed if you need to locally build a derivative image.
Also check out the Caveats section at the end to learn what this template does not do well.
Result
Multi-component service
Above example of a multi-component (two in this case) grafana service will give you this directory structure:
.
└── grafana
├── build-context
│ ├── grafana
│ │ ├── docker-data
│ │ │ └── .gitkeep
│ │ ├── Dockerfile
│ │ └── extras
│ │ └── .gitkeep
│ └── nginx
│ ├── docker-data
│ │ └── .gitkeep
│ ├── Dockerfile
│ └── extras
│ └── .gitkeep
├── common-settings.yml
├── docker-compose.override.yml
├── docker-compose.yml
└── env
└── fully.qualified.domain.name.example
Check out file contents over in the examples/grafana subdir.
Single-component service
With an alternative single-component hashicorpvault service the result may look like this:
.
└── hashicorpvault
├── build-context
│ ├── docker-data
│ │ └── .gitkeep
│ ├── Dockerfile
│ └── extras
│ └── .gitkeep
├── common-settings.yml
├── docker-compose.override.yml
├── docker-compose.yml
└── env
└── fully.qualified.domain.name.example
Check out file contents over in the examples/hashicorpvault subdir.
Caveats
Consider Cookiecutter's project directory and rendered files a starting point. It won't do everything perfectly.
Imagine if you will a service that consists of Infinispan among other things. In Docker Hub's content-addressable image store Infinispan's location is at infinispan/server so you obviously want that exact string with a forward slash to show up in your docker-compose.yml as the image: key's value, same with your Dockerfile. The image: key's value comes from what you enter in Cookiecutter's component_list prompt. Component strings are then used to also pre-fill the volumes: key.
This will cause obvious issues (but the image: key is kinda correct):
services:
infinispan/server:
image: "infinispan/server:${INFINISPAN/SERVER_VERSION}"
container_name: "cacheman-infinispan/server-${CONTEXT}"
This won't cause issues (but you'll have to then go in and manually change the image: key to use infinispan/server):
services:
infinispan:
image: "infinispan:${INFINISPAN_VERSION}"
container_name: "cacheman-infinispan-${CONTEXT}"
You're going to want to keep it simple and go with option 2.