version: "3.9" ######### IMPORTANT ############# # docker-compose-t2.yml is my main docker compose that runs on the same Proxmox host. # You will find only a few apps in this web stack that hosts a few wordpress and non-wordpress sites. # You can copy-paste services from one docker-compose file in this repo to another to add other apps. ########################### SYSTEM DESCRIPTION # DOCKER-COMPOSE FOR WORDPRESS / WEB SERVER # PROXMOX HOST: Dual Intel Xeon 5420, 16 GB RAM, 240 GB SSD, and 2 TB HDD # LXC CONTAINER: 4 CORES, 4 GB RAM, Ubuntu 20.04, and Docker # 32 GB SSD for / ########################### NETWORKS # There is no need to create any networks outside this docker-compose file. # You may customize the network subnets (192.168.90.0/24 and 91.0/24) below as you please. # Docker Compose version 3.5 or higher required to define networks this way. networks: t2_proxy: name: t2_proxy driver: bridge ipam: config: - subnet: 192.168.90.0/24 default: driver: bridge socket_proxy: name: socket_proxy driver: bridge ipam: config: - subnet: 192.168.91.0/24 ########################### SECRETS secrets: htpasswd: file: $DOCKERDIR/secrets/htpasswd cloudflare_email: file: $SECRETSDIR/cloudflare_email cloudflare_api_key: file: $SECRETSDIR/cloudflare_api_key mysql_root_password: file: $SECRETSDIR/mysql_root_password authelia_jwt_secret: file: $SECRETSDIR/authelia_jwt_secret authelia_session_secret: file: $SECRETSDIR/authelia_session_secret authelia_storage_mysql_password: file: $SECRETSDIR/authelia_storage_mysql_password authelia_notifier_smtp_password: file: $SECRETSDIR/authelia_notifier_smtp_password authelia_duo_api_secret_key: file: $SECRETSDIR/authelia_duo_api_secret_key oauth_secret: file: $SECRETSDIR/oauth_secret google_client_secret: file: $SECRETSDIR/google_client_secret google_client_id: file: $SECRETSDIR/google_client_id my_email: file: $SECRETSDIR/my_email ########################### EXTENSION FIELDS # Helps eliminate repetition of sections # More Info on how to use this: https://github.com/htpcBeginner/docker-traefik/pull/228 # Common environment values x-environment: &default-tz-puid-pgid TZ: $TZ PUID: $PUID PGID: $PGID # Proxy Network and Security x-network-and-security: &network-and-security networks: - t2_proxy security_opt: - no-new-privileges:true # Keys common to some of the services in basic-services.txt x-common-keys-basic: &common-keys-basic <<: *network-and-security restart: always # profiles: # - basic # Keys common to some of the dependent services/apps x-common-keys-apps: &common-keys-apps <<: *network-and-security restart: unless-stopped # profiles: # - apps # Keys common to some of the services in media-services.txt x-common-keys-media: &common-keys-media <<: *network-and-security restart: "no" # profiles: # - media ########################### SERVICES services: ############################# FRONTENDS # Traefik 2 - Reverse Proxy # Touch (create empty files) traefik.log and acme/acme.json. Set acme.json permissions to 600. # touch $DOCKERDIR/traefik2/acme/acme.json # chmod 600 $DOCKERDIR/traefik2/acme/acme.json # touch $DOCKERDIR/traefik2/traefik.log traefik: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: traefik image: traefik:2.5 command: # CLI arguments - --global.checkNewVersion=true - --global.sendAnonymousUsage=true - --entryPoints.http.address=:80 - --entryPoints.https.address=:443 # Allow these IPs to set the X-Forwarded-* headers - Cloudflare IPs: https://www.cloudflare.com/ips/ - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22 - --entryPoints.traefik.address=:8080 # - --entryPoints.ping.address=:8081 - --api=true # - --api.insecure=true - --api.dashboard=true #- --ping=true #- --pilot.token=$TRAEFIK_PILOT_TOKEN # - --serversTransport.insecureSkipVerify=true - --log=true - --log.level=WARN # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC - --accessLog=false - --accessLog.filePath=/traefik.log - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines - --accessLog.filters.statusCodes=400-499 - --providers.docker=true # - --providers.docker.endpoint=unix:///var/run/docker.sock # Use Docker Socket Proxy instead for improved security - --providers.docker.endpoint=tcp://socket-proxy:2375 # Automatically set Host rule for services # - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME0`) - --providers.docker.exposedByDefault=false # - --entrypoints.https.http.middlewares=chain-oauth@file - --entrypoints.https.http.tls.options=tls-opts@file # Add dns-cloudflare as default certresolver for all services. Also enables TLS and no need to specify on individual services - --entrypoints.https.http.tls.certresolver=dns-cloudflare - --entrypoints.https.http.tls.domains[0].main=$DOMAINNAME0 - --entrypoints.https.http.tls.domains[0].sans=*.$DOMAINNAME0 # - --entrypoints.https.http.tls.domains[1].main=$DOMAINNAME1 # Pulls main cert for second domain # - --entrypoints.https.http.tls.domains[1].sans=*.$DOMAINNAME1 # Pulls wildcard cert for second domain - --providers.docker.network=t2_proxy - --providers.docker.swarmMode=false - --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory # - --providers.file.filename=/path/to/file # Load dynamic configuration from a file - --providers.file.watch=true # Only works on top level files in the rules folder # - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53 - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.delayBeforeCheck=90 # To delay DNS check and reduce LE hitrate networks: t2_proxy: ipv4_address: 192.168.90.254 # You can specify a static IP socket_proxy: #healthcheck: # test: ["CMD", "traefik", "healthcheck", "--ping"] # interval: 5s # retries: 3 ports: - target: 80 published: 80 protocol: tcp mode: host - target: 443 published: 443 protocol: tcp mode: host # - target: 8080 # published: 8080 # protocol: tcp # mode: host volumes: - $DOCKERDIR/appdata/traefik2/rules:/rules # file provider directory # - /var/run/docker.sock:/var/run/docker.sock:ro # Use Docker Socket Proxy instead for improved security - $DOCKERDIR/appdata/traefik2/acme/acme.json:/acme.json # cert location - you must touch this file and change permissions to 600 - $DOCKERDIR/appdata/traefik2/traefik.log:/traefik.log # for fail2ban - make sure to touch file before starting container environment: - CF_API_EMAIL_FILE=/run/secrets/cloudflare_email - CF_API_KEY_FILE=/run/secrets/cloudflare_api_key - HTPASSWD_FILE=/run/secrets/htpasswd # HTPASSWD_FILE can be whatever as it is not used/called anywhere. secrets: - cloudflare_email - cloudflare_api_key - htpasswd labels: #- "autoheal=true" - "traefik.enable=true" # HTTP-to-HTTPS Redirect - "traefik.http.routers.http-catchall.entrypoints=http" - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)" - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" # HTTP Routers - "traefik.http.routers.traefik-rtr.entrypoints=https" - "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME0`)" ## Services - API - "traefik.http.routers.traefik-rtr.service=api@internal" ## Healthcheck/ping #- "traefik.http.routers.ping.rule=Host(`traefik.$DOMAINNAME0`) && Path(`/ping`)" #- "traefik.http.routers.ping.tls=true" #- "traefik.http.routers.ping.service=ping@internal" ## Middlewares - "traefik.http.routers.traefik-rtr.middlewares=chain-oauth@file" # Docker Socket Proxy - Security Enchanced Proxy for Docker Socket socket-proxy: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: socket-proxy image: tecnativa/docker-socket-proxy networks: socket_proxy: ipv4_address: 192.168.91.254 # You can specify a static IP #privileged: true #ports: # - "127.0.0.1:2375:2375" # Port 2375 should only ever get exposed to the internal network. When possible use this line. # I use the next line instead, as I want portainer to manage multiple docker endpoints within my home network. # - "2375:2375" volumes: - "/var/run/docker.sock:/var/run/docker.sock" environment: - LOG_LEVEL=info # debug,info,notice,warning,err,crit,alert,emerg ## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.). # 0 to revoke access. # 1 to grant access. ## Granted by Default - EVENTS=1 - PING=1 - VERSION=1 ## Revoked by Default # Security critical - AUTH=0 - SECRETS=0 - POST=1 # Watchtower # Not always needed - BUILD=0 - COMMIT=0 - CONFIGS=0 - CONTAINERS=1 # Traefik, portainer, etc. - DISTRIBUTION=0 - EXEC=0 - IMAGES=1 # Portainer - INFO=1 # Portainer - NETWORKS=1 # Portainer - NODES=0 - PLUGINS=0 - SERVICES=1 # Portainer - SESSION=0 - SWARM=0 - SYSTEM=0 - TASKS=1 # Portaienr - VOLUMES=1 # Portainer # Google OAuth - Single Sign On using OAuth 2.0 # https://www.smarthomebeginner.com/google-oauth-with-traefik-docker/ oauth: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: oauth image: thomseddon/traefik-forward-auth:latest # image: thomseddon/traefik-forward-auth:2.1-arm # Use this image with Raspberry Pi # Allow apps to bypass OAuth. Radarr example below will bypass OAuth if API key is present in the request (eg. from NZB360 mobile app). # While this is one way, the recommended way is to bypass authentication using Traefik labels shown in some of the apps later. # command: --rule.radarr.action=allow --rule.radarr.rule="Headers(`X-Api-Key`, `$RADARR_API_KEY`)" # command: --rule.sabnzbd.action=allow --rule.sabnzbd.rule="HeadersRegexp(`X-Forwarded-Uri`, `$SABNZBD_API_KEY`)" environment: - PROVIDERS_GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID - PROVIDERS_GOOGLE_CLIENT_SECRET=$GOOGLE_CLIENT_SECRET - SECRET=$OAUTH_SECRET - COOKIE_DOMAIN=$DOMAINNAME0 - INSECURE_COOKIE=false - AUTH_HOST=oauth.$DOMAINNAME0 - URL_PATH=/_oauth - WHITELIST=$MY_EMAIL - LOG_LEVEL=warn - LOG_FORMAT=text - LIFETIME=86400 # 1 day - DEFAULT_ACTION=auth - DEFAULT_PROVIDER=google secrets: # had trouble getting secrets to work: https://github.com/thomseddon/traefik-forward-auth/issues/155#issuecomment-664630985 - google_client_id - google_client_secret - oauth_secret - my_email labels: - "traefik.enable=true" ## HTTP Routers - "traefik.http.routers.oauth-rtr.tls=true" - "traefik.http.routers.oauth-rtr.entrypoints=https" - "traefik.http.routers.oauth-rtr.rule=Host(`oauth.$DOMAINNAME0`)" ## Middlewares - "traefik.http.routers.oauth-rtr.middlewares=chain-oauth@file" ## HTTP Services - "traefik.http.routers.oauth-rtr.service=oauth-svc" - "traefik.http.services.oauth-svc.loadbalancer.server.port=4181" # Portainer - WebUI for Containers portainer: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: portainer image: portainer/portainer-ce:latest # command: -H unix:///var/run/docker.sock # # Use Docker Socket Proxy instead for improved security command: -H tcp://socket-proxy:2375 networks: - t2_proxy - socket_proxy volumes: # - /var/run/docker.sock:/var/run/docker.sock:ro # # Use Docker Socket Proxy instead for improved security - $DOCKERDIR/appdata/portainer/data:/data # Change to local directory if you want to save/transfer config locally environment: - TZ=$TZ labels: - "traefik.enable=true" ## HTTP Routers - "traefik.http.routers.portainer-rtr.entrypoints=https" - "traefik.http.routers.portainer-rtr.rule=Host(`portainer.$DOMAINNAME0`)" ## Middlewares - "traefik.http.routers.portainer-rtr.middlewares=chain-oauth@file" ## HTTP Services - "traefik.http.routers.portainer-rtr.service=portainer-svc" - "traefik.http.services.portainer-svc.loadbalancer.server.port=9000" # Autoindex - Simple Directory Index autoindex: <<: *common-keys-apps # See EXTENSION FIELDS at the top container_name: autoindex image: dceoy/nginx-autoindex:latest # ports: # - "$AUTOINDEX_PORT:80" volumes: #- $USERDIR:/var/lib/nginx/html:ro # Location you want to index - $USERDIR:/var/lib/nginx/html:ro # Location you want to index labels: - "traefik.enable=true" ## HTTP Routers - "traefik.http.routers.autoindex-rtr.entrypoints=https" - "traefik.http.routers.autoindex-rtr.rule=Host(`index.$DOMAINNAME0`)" ## Middlewares - "traefik.http.routers.autoindex-rtr.middlewares=chain-oauth@file" ## HTTP Services - "traefik.http.routers.autoindex-rtr.service=autoindex-svc" - "traefik.http.services.autoindex-svc.loadbalancer.server.port=80" ############################# DATABASE # MariaDB - MySQL Database # After starting container for first time dexec and mysqladmin -u root password mariadb: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: mariadb image: lscr.io/linuxserver/mariadb ports: - "$MARIADB_PORT:3306" volumes: - $DOCKERDIR/appdata/mariadb/data:/config environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - FILE__MYSQL_ROOT_PASSWORD=/run/secrets/mysql_root_password # Note FILE__ (double underscore) - Issue #127 secrets: - mysql_root_password # InfluxDB - Database for sensor data # Create influxdb.conf influxdb: <<: *common-keys-basic # See EXTENSION FIELDS at the top image: influxdb:latest container_name: influxdb ports: - "$INFLUXDB_PORT:8086" - "$INFLUXDB_PORT_PROXMOX:8087/udp" volumes: - $DOCKERDIR/appdata/influxdb/etc/influxdb.conf:/etc/influxdb/influxdb.conf:ro - $DOCKERDIR/appdata/influxdb/db:/var/lib/influxdb # command: -config /etc/influxdb/influxdb.conf # Redis - Key-value Store redis: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: redis image: redis:latest entrypoint: redis-server --appendonly yes --requirepass $REDIS_PASSWORD --maxmemory 512mb --maxmemory-policy allkeys-lru ports: - "$REDIS_PORT:6379" volumes: - $DOCKERDIR/appdata/redis/data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro # Redis Commander - Redis Management Tool rediscommander: <<: *common-keys-apps # See EXTENSION FIELDS at the top container_name: rediscommander image: rediscommander/redis-commander:latest # ports: # - "$REDISCOMMANDER_PORT:8081" environment: - REDIS_HOST=$REDIS_HOST - REDIS_PASSWORD=$REDIS_PASSWORD labels: - "traefik.enable=true" ## HTTP Routers - "traefik.http.routers.rediscommander-rtr.entrypoints=https" - "traefik.http.routers.rediscommander-rtr.rule=Host(`rediscom.$DOMAINNAME0`)" ## Middlewares - "traefik.http.routers.rediscommander-rtr.middlewares=chain-oauth@file" ## HTTP Services - "traefik.http.routers.rediscommander-rtr.service=rediscommander-svc" - "traefik.http.services.rediscommander-svc.loadbalancer.server.port=8081" # phpMyAdmin - Database management # Create a new user with admin privileges. Cannot login as MySQL root for some reason. phpmyadmin: <<: *common-keys-apps # See EXTENSION FIELDS at the top image: phpmyadmin/phpmyadmin:latest container_name: phpmyadmin # ports: # - "$PHPMYADMIN_PORT:80" # volumes: # - $DOCKERDIR/appdata/phpmyadmin:/etc/phpmyadmin environment: - PMA_HOST=$MARIADB_HOST - PMA_PORT=$MARIADB_PORT #- PMA_ARBITRARY=1 - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_password secrets: - mysql_root_password labels: - "traefik.enable=true" ## HTTP Routers - "traefik.http.routers.phpmyadmin-rtr.entrypoints=https" - "traefik.http.routers.phpmyadmin-rtr.rule=Host(`pma.$DOMAINNAME0`)" ## Middlewares - "traefik.http.routers.phpmyadmin-rtr.middlewares=chain-oauth@file" ## HTTP Services - "traefik.http.routers.phpmyadmin-rtr.service=phpmyadmin-svc" - "traefik.http.services.phpmyadmin-svc.loadbalancer.server.port=80" ########################### WEB # Nginx - Web Server nginx: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: nginx image: nginx:1.20 # 1.18 # Updated 8/9/2021 depends_on: - php7 volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - /var/log/nginx:/var/log/nginx - $DOCKERDIR/appdata/nginx:/etc/nginx - $DOCKERDIR/shared/.htpassd:/shared/.htpasswd - $DOCKERDIR/sites/shb/html:/var/www/html/shb - $DOCKERDIR/sites/shb/beta:/var/www/html/beta - $DOCKERDIR/sites/khub/html:/var/www/html/khub - $DOCKERDIR/sites/dash/html:/var/www/html/dash labels: - "traefik.enable=true" ## HTTP Routers SHB (WordPress) Auth - "traefik.http.routers.nginx-shb-auth-rtr.entrypoints=https" - "traefik.http.routers.nginx-shb-auth-rtr.rule=Host(`www.$DOMAINNAME0`) && Path(`/wp-login.php`)" - "traefik.http.routers.nginx-shb-auth-rtr.priority=100" ## HTTP Routers SHB (WordPress) Bypass - "traefik.http.routers.nginx-shb-rtr.entrypoints=https" - "traefik.http.routers.nginx-shb-rtr.rule=Host(`$DOMAINNAME0`) || Host(`www.$DOMAINNAME0`)" - "traefik.http.routers.nginx-shb-rtr.priority=99" ## HTTP Routers SHB Beta (WordPress) - "traefik.http.routers.nginx-shb-beta-rtr.entrypoints=https" - "traefik.http.routers.nginx-shb-beta-rtr.rule=Host(`beta.$DOMAINNAME0`)" ## HTTP Routers DASH (non-WordPress) - "traefik.http.routers.nginx-dash-rtr.entrypoints=https" - "traefik.http.routers.nginx-dash-rtr.rule=Host(`dash.$DOMAINNAME0`)" ## HTTP Routers KHUB (non-WordPress) - "traefik.http.routers.nginx-khub-rtr.entrypoints=https" - "traefik.http.routers.nginx-khub-rtr.rule=Host(`$DOMAINNAME1`) || Host(`www.$DOMAINNAME1`)" # Redirect shb non-www to www middleware - "traefik.http.middlewares.shb-redirect.redirectregex.regex=^https?://$DOMAINNAME0/(.*)" - "traefik.http.middlewares.shb-redirect.redirectregex.replacement=https://www.$DOMAINNAME0/$${1}" - "traefik.http.middlewares.shb-redirect.redirectregex.permanent=true" # Redirect khub non-www to www middleware - "traefik.http.middlewares.khub-redirect.redirectregex.regex=^https?://$DOMAINNAME1/(.*)" - "traefik.http.middlewares.khub-redirect.redirectregex.replacement=https://www.$DOMAINNAME1/$${1}" - "traefik.http.middlewares.khub-redirect.redirectregex.permanent=true" ## Middlewares - "traefik.http.routers.nginx-khub-rtr.middlewares=khub-redirect,chain-no-auth@file" - "traefik.http.routers.nginx-shb-rtr.middlewares=shb-redirect,chain-no-auth-wp@file" #- "traefik.http.routers.nginx-shb-auth-rtr.middlewares=shb-redirect,chain-oauth-wp@file" - "traefik.http.routers.nginx-shb-auth-rtr.middlewares=shb-redirect,chain-no-auth-wp@file" - "traefik.http.routers.nginx-dash-rtr.middlewares=chain-oauth@file" - "traefik.http.routers.nginx-shb-beta-rtr.middlewares=chain-oauth@file" ## HTTP Services - "traefik.http.routers.nginx-shb-rtr.service=nginx-svc" - "traefik.http.routers.nginx-shb-auth-rtr.service=nginx-svc" - "traefik.http.routers.nginx-khub-rtr.service=nginx-svc" - "traefik.http.routers.nginx-dash-rtr.service=nginx-svc" - "traefik.http.routers.nginx-shb-beta-rtr.service=nginx-svc" - "traefik.http.services.nginx-svc.loadbalancer.server.port=80" # PHP - Hypertext Preprocessor php7: <<: *common-keys-basic # See EXTENSION FIELDS at the top container_name: php7 image: php:7.4-fpm-custom build: context: $DOCKERDIR/custom/ dockerfile: Dockerfile-php7 user: $PUID:$PGID # allows upgrading WP and plugins volumes: - $DOCKERDIR/sites/shb/html:/var/www/html/shb - $DOCKERDIR/sites/shb/beta:/var/www/html/beta - $DOCKERDIR/appdata/php/php7:/usr/local/etc/php - $DOCKERDIR/sites/khub/html:/var/www/html/khub - $DOCKERDIR/sites/dash/html:/var/www/html/dash ########################### UTILITIES # VSCode - VSCode Editing vscode: <<: *common-keys-basic # See EXTENSION FIELDS at the top image: codercom/code-server:latest container_name: vscode volumes: - $USERDIR/server:/home/coder/server - $DOCKERDIR:/home/coder/docker - $DOCKERDIR/appdata/vscode:/home/coder environment: PASSWORD: $VSCODE_PASSWORD # Run as root first, create the directories, then change permissions to user:docker and 775. Disable run as root below. user: $PUID:$PGID #user: "0" DOCKER_HOST: tcp://socket-proxy:2375 labels: - "traefik.enable=true" ## HTTP Routers - "traefik.http.routers.vscode-rtr.entrypoints=https" - "traefik.http.routers.vscode-rtr.rule=Host(`code.$DOMAINNAME0`)" ## Middlewares - "traefik.http.routers.vscode-rtr.middlewares=chain-oauth@file" ## HTTP Services - "traefik.http.routers.vscode-rtr.service=vscode-svc" - "traefik.http.services.vscode-svc.loadbalancer.server.port=8080" ############################# MAINTENANCE # Docker-GC - Automatic Docker Garbage Collection # Create docker-gc-exclude file dockergc: <<: *common-keys-apps # See EXTENSION FIELDS at the top image: clockworksoul/docker-gc-cron:latest container_name: docker-gc networks: - socket_proxy volumes: # - /var/run/docker.sock:/var/run/docker.sock # Use Docker Socket Proxy instead for improved security - $DOCKERDIR/appdata/docker-gc/docker-gc-exclude:/etc/docker-gc-exclude environment: CRON: 12 0 0 * * ? # Everyday at midnight. FORCE_IMAGE_REMOVAL: 1 FORCE_CONTAINER_REMOVAL: 0 GRACE_PERIOD_SECONDS: 604800 DRY_RUN: 0 CLEAN_UP_VOLUMES: 1 TZ: $TZ DOCKER_HOST: tcp://socket-proxy:2375