Docker-compose Tips

Index.js


  • Validation
  • Environment Variables
  • Multiple compose files
  • External Networks
  • Commands
  • Anchors

Validation

docker-compose config validates and outputs configuration.
It's essential in more advanced usages, as we'll see.

dc config - error


								# docker-compose.yml
								version: '3.3'

								service:  # Typo here
								  app:
								    image: nginx/alpine
							

								$ docker-compose config

								ERROR: The Compose file is invalid because:

								Invalid top-level property "service".
								Valid top-level sections for this Compose file are:
								  version, services, networks, volumes, secrets, configs,
								  and extensions starting with "x-".
							
Spoiler alert: extensions

dc config - good boy


								# docker-compose.yml
								version: '3.3'

								services:
								  app:
								    image: nginx/alpine
							

									$ docker-compose config

									services:
									  app:
										image: nginx/alpine
									version: '3.3'
								
Side note: changed order of yml sections

Environment Variables

docker-compose can make use of environment variables to be more configurable and dynamic.

Environment Variables - Example


								# docker-compose.yml
								version: '3.3'

								services:
								  app:
								    image: my-registry/my-docker-image:${TAG}
							

									$ export TAG=v3.1.0
									$ docker-compose config

									services:
									  app:
										image: my-registry/my-docker-image:v3.1.0
									version: '3.3'
								
Defaults could be provided with the syntax:
${VARIABLE:-default} or ${VARIABLE:default}

.env special file


								# .env
								TAG=v3.2.0
							

								# docker-compose.yml
								version: '3.3'

								services:
								  app:
								    image: my-registry/my-docker-image:${TAG}
							

									$ docker-compose config

									services:
									  app:
										image: my-registry/my-docker-image:v3.2.0
									version: '3.3'
								
If a .env file exists, it'll be used as source for env vars.

Multiple files

docker-compose can accepts more than one file, overriding values.
This behaviour augments exponentially the compose capabilities

multiple files - example


								# docker-compose.yml
								version: "3.3"
								services:
								  app:
								    image: nginx/alpine
							

								# docker-compose.prod.yml
								version: "3.3"
								services:
								  app:
								    volumes:
									  - "./config/:/app/config/"
							

								$ docker-compose -f docker-compose.yml -f docker-compose.prod.yml config
								services:
								  app:
								    image: nginx/alpine
								    volumes:
								      - /absolute/path/calculated/config:/app/config:rw
								version: '3.3'
							

multiple files - fail

From great powers ... come greater fails

multiple files - fail


								# docker-compose.yml
								version: "3.3"
								services:
								  app:
								    image: nginx/alpine
								    ports:
									- "8080:8080"
							

								# docker-compose.prod.yml
								version: "3.3"
								services:
								  app:
								    ports:
									- "8181:8080"
							

$ docker-compose -f docker-compose.yml -f docker-compose.prod.yml config
								
What will be the rendered ports property?

services:
  app:
    image: nginx/alpine
    ports:
      - "8080:8080"
      - "8181:8080"
version: '3.3'
								
YAML lists are appended, not overridden

multiple files - the correct way


								# docker-compose.local.yml
								version: "3.3"
								services:
								  app:
								    ports:
									- "8080:8080"
							

								# docker-compose.prod.yml
								version: "3.3"
								services:
								  app:
								    ports:
									- "8181:8080"
							

								# docker-compose.yml
								version: "3.3"
								services:
								  app:
								    image: my-registry/my-image:$TAG
							

								$ TAG=v6.6.6 docker-compose -f docker-compose.yml -f docker-compose.prod.yml config
								services:
								  app:
								    image: my-registry/my-image:v6.6.6
								    ports:
									- "8181:8080"
								version: '3.3'
							

multiple files - via env var

It's possible to use an environment variable to specify compose files.

								# .env
								COMPOSE_FILE=docker-compose.yml:docker-compose.local.yml
								# ":" separated string
								TAG=latest
							

								$ docker-compose config
								services:
								  app:
								    image: my-registry/my-image:latest
								    ports:
									- "8080:8080"
								version: '3.3'
							

Networking

docker-compose networking is flexible, and permits to use existing (external) networks, and also control how the internal DNS will behave

Attaching to other networks - Use Case

Attaching to other networks - Compose


# docker-compose.serviceB.yml
version: '3.7'
services:
  serviceB:
    build: { "context": "." }
    networks:
      otherComposeNetwork:
        aliases:
          - ${NETWORK_SERVICE_ALIAS:-serviceB}
networks:
  otherComposeNetwork:
    external:
      name: ${NETWORK_NAME:-crystal_framework}
							

$ docker network list
NETWORK ID          NAME                     DRIVER              SCOPE
b753eefc8242        somecompose_network      bridge              local

$ docker-compose -f other-compose.yml stop serviceName

$ export NETWORK_SERVICE_ALIAS=serviceName
$ export NETWORK_NAME=somecompose_network
$ docker-compose up
								
Et voila'!

Commands

It's possible to exec into running containers.
Very useful for running integration/e2e tests!

							$ docker-compose exec serviceName npm integration
						

Anchors

Docker-compose will ignore "x-" keys in validation, in that way is possible to use normal YAML anchors.

version: '3.4'
x-logging:
  &default-logging
  options:
    max-size: '12m'
    max-file: '5'
  driver: json-file

services:
  web:
    image: myapp/web:latest
    logging: *default-logging
  db:
    image: mysql:latest
    logging: *default-logging
									

$ docker-compose config
services:
  db:
    image: mysql:latest
    logging:
      driver: json-file
      options:
        max-file: '5'
        max-size: 12m
  web:
    image: myapp/web:latest
    logging:
      driver: json-file
      options:
        max-file: '5'
        max-size: 12m
version: '3.4'
									

Useful links

Q & A❓

Thanks! Bye! 👋