Docker Compose

Please read our disclaimer https://docs.ibracorp.io/#disclaimer.

You can find our docker-compose templates here, feel free to contribute!

What is docker compose?

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.

Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.

Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.

  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.

  3. Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using the docker-compose binary.

Source: https://docs.docker.com/compose/

Install docker compose:

Always worth checking the official docs:

If you followed the commands to install docker here for Ubuntu for example - https://docs.docker.com/engine/install/ubuntu/

You can run the following command to install docker compose v1 (where you have to run the command with docker-compose up -d)

sudo apt install docker-compose

Or the following command for v2 (where you have to run the command with docker compose up -d)

sudo apt install docker-compose-plugin

Compose examples with .env files for variables

Docker compose can be run with variable set in an .env file. If this file is in the same directory as the compose file, it will pick this up automatically.

PLEASE NOTE

With these examples, we have labels for Traefik. if you do not use Traefik, you can simply remove the whole labels section.

An example of a docker-compose.yml file:

docker-compose.yml
version: '3'
services:
  auth:
    container_name: auth    
    image: authelia/authelia:latest
    ports:
      - 9091:9091
    volumes:
      - ${APP_DIR:?err}/authelia:/config
    labels:
      traefik.enable: true
      traefik.http.routers.authelia.entryPoints: https
    networks:
      - proxy
    restart: unless-stopped

networks:
  proxy:
    driver: bridge
    external: true

TIP

The first value under ports is always the host.

For example with ports:

    ports:
      - 9080:9091

This will bind the container port 9091 to the hosts port 9080

For example with volumes:

    volumes:
      - /opt/appdata/authelia:/config

This will bind the container folder /config to the hosts path /opt/appdata/authelia

Example of a .env file

.env
APP_DIR=/opt/appdata

Example how you can combine apps you want to run together and rely on each other to run. You can add a “depends_on” variable which will not run the container until the others are already running.

You can also separate services on their own secure network and only give access to the apps that require it (example below has Redis and MariaDB on a secure, separated network).

version: '3'
services:
  auth:
    container_name: auth  
    image: authelia/authelia:latest
    ports:
      - 9091:9091
    volumes:
      - ${APP_DIR:?err}/authelia:/config
    labels:
      traefik.enable: true
      traefik.http.routers.authelia.entryPoints: https
    networks:
      - proxy
      - secure
    restart: unless-stopped
    depends_on:
      - redis
      - mariadb

  redis:
    container_name: redis
    image: bitnami/redis:latest
    ports:
      - 6379:6379
    volumes:
      - ${APP_DIR:?err}/redis:/bitnami/
    environment:
      REDIS_PASSWORD: "${REDIS_PASSWORD:?err}"
    networks:
      - secure
    restart: unless-stopped

  mariadb:
    container_name: mariadb
    image: linuxserver/mariadb:latest
    expose:
      - 3306:3306
    volumes:
      - ${APP_DIR:?err}/mariadb:/config
    environment:
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:?err}"    
    networks:
      - secure
    restart: unless-stopped

networks:
  proxy:
    driver: bridge
    external: true
  secure:
    driver: bridge
    external: true

TIP

As you can see above, you can add a container to multiple networks by using the follwing format:

    networks:
      - proxy
      - secure

Just note that these are both also defined at the bottom of the compose file:

networks:
  proxy:
    driver: bridge
    external: true
  secure:
    driver: bridge
    external: true

If all the containers in the compose file are going to be on the same network, you can define a network as default for all containers at the bottom of the file. This means you then do not have to define the "networks:" variable on each container.

networks:
  default:
    external: true
    name: proxy

Linked .env file example

APP_DIR=/opt/appdata
REDIS_PASSWORD=SuperSecurePassword
MYSQL_ROOT_PASSWORD=EvenMoreSecurePassword

Plex Example for Quicksync

version: '3'
services:
  plex:
    container_name: "plex"
    image: "${MAINTAINER:?err}/plex:latest"
    ports:
      - "32400:32400"
    volumes:
      - "${APP_DIR:?err}/plex/database:/config:rw"
      - "/mnt:/mnt:ro"
      - "${TRANSCODE_DIR:?err}:/transcode:rw"
    labels:
      traefik.enable: true
      traefik.http.routers.plex.entryPoints: https
    environment:
      TZ: ${TZ:?err}
      PGID: ${ID:?err}
      PUID: ${ID:?err}
      UMASK: ${UMASK:?err}
      PLEX_CLAIM: ${PLEX_CLAIM_ID:?err}
      VERSION: ${PLEX_VERSION:?err}
    networks:
      - proxy
    restart: unless-stopped
    devices:
       - /dev/dri:/dev/dri

networks:
  proxy:
    driver: bridge
    external: true

TIP

If you would like to bind a folder from the host as read-only, you can do this with the following addition to the volume paths "ro":

    volumes:
      - "/mnt:/mnt:ro"

If you would like to bind a folder from the host as read-write, you can do this with the following addition to the volume paths "rw":

    volumes:
      - "/mnt:/mnt:rw"

.env file to match

MAINTAINER=hotio
APP_DIR=/docker
TRANSCODE_DIR=/dev/shm
TZ=Europe/London
ID=1000
UMASK=002
PLEX_CLAIM_ID=ELOAIE94J4OIFJSPE049FJ
PLEX_VERSION=docker

Plex Example for Nvidia

version: '3'
services:
  plex:
    container_name: "plex"
    image: "${MAINTAINER:?err}/plex:latest"
    ports:
      - "32400:32400"
    volumes:
      - "${APP_DIR:?err}/plex/database:/config:rw"
      - "/mnt:/mnt:ro"
      - "${TRANSCODE_DIR:?err}:/transcode:rw"
    labels:
      traefik.enable: true
      traefik.http.routers.plex.entryPoints: https
    environment:
      TZ: ${TZ:?err}
      PGID: ${ID:?err}
      PUID: ${ID:?err}
      UMASK: ${UMASK:?err}
      PLEX_CLAIM: ${PLEX_CLAIM_ID:?err}
      VERSION: ${PLEX_VERSION:?err}
      NVIDIA_VISIBLE_DEVICES: all
    networks:
      - proxy
    restart: unless-stopped
    runtime: nvidia

networks:
  proxy:
    driver: bridge
    external: true

TIP

If you would like to add multiple port mappings from the container to the host, you can add them all under the ports: section.

You can also define the protocal used on each port if required with "/tcp" or "/udp".

    ports:
      - "32400:32400"
      - "1900:1900/udp"
      - "3005:3005"
      - "5353:5353/udp"
      - "8324:8324"
      - "32410:32410/udp"
      - "32412:32412/udp"
      - "32413:32413/udp"
      - "32414:32414/udp"
      - "32469:32469"

.env file to match

MAINTAINER=linuxserver
APP_DIR=/opt/appdata
TRANSCODE_DIR=/dev/shm
TZ=Europe/London
ID=1000
UMASK=002
PLEX_CLAIM_ID=ELOAIE94J4OIFJSPE049FJ
PLEX_VERSION=docker

Global .env Trick

A trick you can do with the .env file is you can just create one file, with all your values, then hardlink it to each directory where your docker compose files are. This means you only have to add the variables once, to one file, and if you change it, it changes everywhere. You can hardlink the global .env file with the following command:

ln /path/to/global/.env /path/to/app_folder/.env

Start the Container

Then simply run the docker compose run command to start the container (remember to run these commands from within the folder where the compose file is):

docker-compose up -d

Update the container

Pulling the latest version of an app is easy, simply pull the latest image and then restart the app (remember to run these commands from within the folder where the compose file is):

docker-compose pull
docker-compose restart

Check container logs using compose

docker-compose logs

Special Thanks

  • Our Discord community our Community Leaders oldcrazyeye, DiscDuck and Sycotix for their input and documentation.

Final Words

We hope you enjoyed this guide. It was conceptualized, written, and implemented by our Community Leader Hawks.

Support Us

Our work sometimes takes months to research and develop. If you want to help support us please consider:

Thank you for being part of our community!

Last updated