Skip to content

Instantly share code, notes, and snippets.

@efossas
Last active August 19, 2018 19:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save efossas/395f8b81fbd2b4f09a839437ba7b6031 to your computer and use it in GitHub Desktop.
Save efossas/395f8b81fbd2b4f09a839437ba7b6031 to your computer and use it in GitHub Desktop.
docker-compose.yml
# set the version of Docker compose to use
# avoiding the minor number just uses the latest version, i.e. 3 -> 3.7
version: '3'
# our Docker networks. we create just one: 'proxy'
# we set 'proxy' to use the 'bridge' driver, which actually happens by default if that field is omitted
# since our containers aren't on the 'host' network, they will be isolated from the host until we do some port mapping/exposing
# if you don't define a network, docker compose will create a 'default' network and put all services/containers on it
networks:
proxy:
driver: bridge
# our Docker named volumes. we create two: 'db-mongo' & 'cache-redis'
# when containers are removed, any data they created are destroyed
# we attach volumes to containers to make data persistent
volumes:
db-mongo:
cache-redis:
# our Docker services. each container becomes a service
# in Docker world, a service is just a container with extra info on how to deploy it
services:
# define the Traefik service
traefik:
# set the image to use
image: 'traefik:alpine'
# set the container name, it defaults to the service name if not defined
container_name: 'traefik'
# expose port 8080 on the container.
# Exposed ports are only accessible to other containers on the same Docker network like so -> http://CONTAINER:PORT
expose:
- 8080
# map ports from host to container, this is how we make our containers accessible from outside the Docker network
# map host port 80 to container port 80 for http & ditto for 443 https
# so http://127.0.0.1:80 on host routes to port 80 on this container and ditto for port 443.
ports:
- "80:80"
- "443:443"
# these are actually 'bind mounts' which are when you mount a host directory to a container directory
# they're used to share data from the host to a container, typically for development
# they're rarely used in production, since it doesn't scale well (think about binding a single host directory when multiple copies of your service are running on multiple machines)
# for production, you usually build that data into the image (except for secrets, which are another matter)
volumes:
# Traefik auto-detects containers on the network by reading from the Docker socket
- /var/run/docker.sock:/var/run/docker.sock
# this is the Traefik configuration file
- ./traefik.toml:/etc/traefik/traefik.toml
# this directory will store self-signed certificates for enabling TLS (https) connections to Traefik
- ./ssl:/ssl
# labels are just arbitrary metadata
# you can use them to search for containers like so: docker ps --filter 'label=LABEL'
# since Traefik is connected to the docker.sock, it can read the labels on all containers
# so Traefik uses labels to dynamically update its routing
labels:
# accept connections to entry point 'https' & 'http' (these are defined in traefik.toml)
- traefik.frontend.entryPoints=https,http
# if the connection matches this front end rule, route the connection to this container
# in this case, the connection must have a host name of 'traefik.docker.localhost'
- traefik.frontend.rule=Host:traefik.docker.localhost
# route frontend rule matches to port 8080 on this container
- traefik.port=8080
# enable Traefik to route to this container, this isn't always needed (I'll explain more when going over treafik.toml)
- traefik.enable=true
# add this container to the 'proxy' network
networks:
proxy:
# the 'crud' service, it's our Node+Express server
crud:
image: 'efossas/crud'
container_name: 'crud'
expose:
- 80
- 443
volumes:
- ./:/crud
labels:
# the 'INSECURE' part is called a segment label
# you use segments when you need to define routing to more than one port on a container
- traefik.INSECURE.frontend.entryPoints=https,http
- traefik.INSECURE.frontend.rule=Host:crud.docker.localhost
- traefik.INSECURE.port=80
## traefik does not support ssl between containers, and doesn't have a rule for matching http or https (https://github.com/containous/traefik/issues/364)
## so I've commented this out, but it should give you an idea of how segments work
#- traefik.SECURE.frontend.rule=Host:crud.docker.localhost
#- traefik.SECURE.port=443
- traefik.enable=true
# this service won't start until our 'mongo' & 'redis' service has started
depends_on:
- mongo
- redis
networks:
proxy:
# the 'mongo' service, it's our NoSQL database
mongo:
image: 'mongo:xenial'
container_name: 'mongo'
volumes:
# this is a 'named volume'
# we don't need to directly access the directory storing data, but we want the data to persist
# these are definitely used in production
- db-mongo:/data/db
labels:
# we don't want to expose our MongoDB to the world, so we disable Traefik routing here
- traefik.enable=false
networks:
proxy:
# the 'redis' service, it's our key=value database for session cacheing
redis:
image: 'redis:alpine'
container_name: 'redis'
volumes:
- cache-redis:/data
labels:
- traefik.enable=false
networks:
proxy:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment