EatThis.app is currently being hosted on my Digital Ocean box with completely manual setup and deployment process. I would like to get a docker image setup that is based on Nginx and Lets Encrypt so setup and deployment are much easier and less error-prone.
Some useful resources:
And notes from jaecen:
version: "3"
services:
nginx-proxy:
image: jwilder/nginx-proxy:alpine
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/tmp/docker.sock:ro"
- "/etc/certs:/etc/nginx/certs:ro"
- "nginx-vhost:/etc/nginx/vhost.d"
- "nginx-html:/usr/share/nginx/html"
- ./proxy.nginx.conf:/etc/nginx/conf.d/proxy.nginx.conf:ro
environment:
- "ENABLE_IPV6=true"
- "SSL_POLICY=Mozilla-Modern"
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: ""
letsencrypt-companion:
image: jrcs/letsencrypt-nginx-proxy-companion
depends_on:
- nginx-proxy
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "/etc/certs:/etc/nginx/certs:rw"
- "nginx-vhost:/etc/nginx/vhost.d"
- "nginx-html:/usr/share/nginx/html"
uninitialized-net:
image: sebp/lighttpd
depends_on:
- nginx-proxy
- letsencrypt-companion
volumes:
- "/var/www/uninitialized-net/htdocs:/var/www/localhost/htdocs"
environment:
- "VIRTUAL_HOST=uninitialized.net,www.uninitialized.net"
- "LETSENCRYPT_HOST=uninitialized.net,www.uninitialized.net"
- "[email protected]"
- "SSL_POLICY=Mozilla-Modern"
node-uninitialized-net:
image: "node:10-alpine"
depends_on:
- nginx-proxy
- letsencrypt-companion
user: "node"
working_dir: "/home/node/app"
volumes:
- "/var/www/node-uninitialized-net:/home/node/app"
ports:
- "8080"
command: "npm start"
environment:
- "NODE_ENV=production"
- "VIRTUAL_HOST=node.uninitialized.net"
- "VIRTUAL_PORT=8080"
- "LETSENCRYPT_HOST=node.uninitialized.net"
- "[email protected]"
- "SSL_POLICY=Mozilla-Modern"
netcore-uninitialized-net:
image: "jaecen/asp-dot-net-core-docker:latest"
depends_on:
- nginx-proxy
- letsencrypt-companion
environment:
- "VIRTUAL_HOST=netcore.uninitialized.net"
- "LETSENCRYPT_HOST=netcore.uninitialized.net"
- "[email protected]"
- "SSL_POLICY=Mozilla-Modern"
cardnex-us:
image: sebp/lighttpd
depends_on:
- nginx-proxy
- letsencrypt-companion
volumes:
- /var/www/cardnex-us/htdocs:/var/www/localhost/htdocs
environment:
- "VIRTUAL_HOST=cardnex.us,www.cardnex.us"
- "LETSENCRYPT_HOST=cardnex.us,www.cardnex.us"
- "[email protected]"
- "SSL_POLICY=Mozilla-Modern"
bitwarden-uninitialized-net:
image: mprasil/bitwarden
depends_on:
- nginx-proxy
- letsencrypt-companion
volumes:
- /var/bitwarden:/data
environment:
- "SIGNUPS_ALLOWED=false"
- "DOMAIN=https://bitwarden.uninitialized.net"
- "VIRTUAL_HOST=bitwarden.uninitialized.net"
- "LETSENCRYPT_HOST=bitwarden.uninitialized.net"
- "[email protected]"
- "SSL_POLICY=Mozilla-Modern"
# MariaDB, memcached, and seafile are all to support Seafile
mariadb:
image: mariadb:10.1
container_name: seafile-mariadb
environment:
- MYSQL_ROOT_PASSWORD=**** # Requested, set the root's password of MySQL service.
- MYSQL_LOG_CONSOLE=true
volumes:
- /opt/seafile-mysql/db:/var/lib/mysql # Requested, specifies the path to MySQL data persistent store.
memcached:
image: memcached:1.5.6
container_name: seafile-memcached
entrypoint: memcached -m 256
seafile:
image: seafileltd/seafile-mc:latest
container_name: seafile
expose:
- 80
volumes:
- /opt/seafile-data:/shared # Requested, specifies the path to Seafile data persistent store.
- ./seafile.nginx.conf.template:/templates/seafile.nginx.conf.template:ro
environment:
- DB_HOST=mariadb
- DB_ROOT_PASSWD=**** # Requested, the value shuold be root's password of MySQL service.
- TIME_ZONE=America/Los_Angeles # Optional, default is UTC. Should be uncomment and set to your local time zone.
- SEAFILE_ADMIN_EMAIL=**** # Specifies Seafile admin user, default is '[email protected]'.
- SEAFILE_ADMIN_PASSWORD=**** # Specifies Seafile admin password, default is 'asecret'.
- SEAFILE_SERVER_LETSENCRYPT=false # Whether to use https or not.
- SEAFILE_SERVER_HOSTNAME=docs.seafile.com # Specifies your host name if https is enabled.
- "VIRTUAL_HOST=seafile.uninitialized.net"
- "LETSENCRYPT_HOST=seafile.uninitialized.net"
- "[email protected]"
- "SSL_POLICY=Mozilla-Modern"
depends_on:
- mariadb
- memcached
volumes:
nginx-vhost:
nginx-html:
So this is how I run my personal "apps" server. It's where I host everything except my VPN. I have that on a separate machine to reduce the attack surface.
Everything I use is in that docker-compose or in one of the mapped volumes. When I want to start a new service, I add it to the docker-compose file, set the four environment variables, and docker-compose up -d
The parts you'll be interested in are nginx-proxy and letsencrypt-companion. nginx-proxy is the reverse proxy. All requests on :80 and :443 come in to that. It then does a lookup on the host header and routes it to the service with the matching VIRTUAL_HOST environment variable. So, for example, the node-uninitialized-net service is configured with a VIRTAL_HOST of node.uninitialized.net. All requests to that domain get routed to that container.
The letsencrypt-companion service just watches nginx-proxy and sets up Let's Encrypt certs for any container with LETSENCRYPT_HOST and LETSENCRYPT_EMAIL environment variables. It periodically checks the cert expiration and automatically renews as needed. letsencrypt-companion has a tight dependency on nginx-proxy.
You can see that I'm running my own apps for things like netcore-uninitialized-net, lighttpd instances for static sites like cardnex-us, and third-party services like bitwarden and seafile (which depends on mariadb and memcached).
Notably, there is zero infrastructure configuration outside of that docker-compose file except for my firewall configuration, which is just :22, :80, and :443.