Recently I set up my server on DigitalOcean with Docker and Nginx as a reverse proxy. This is a brief description of how I did it and a few Docker commands I found most useful.
Setting up a server
This is roughly similar to this article on Google Cloud, just a stripped and slightly reorganized version.
Creating certs directory
To enable HTTPS, we need certificates. So first we need to create a directory to hold the certs.
cd mkdir certs
We use the Docker Let’s Encrypt nginx-proxy companion to automatically issue and use signed certificates. To do this, we declare volumes when running the reverse-proxy so the
nginx-letsencrypt companion can populate them with certificates.
However, in order for
nginx-proxy to proxy other containers, they have to be on the same Docker network.
Running all the containers
So we first create a network:
docker network create --driver bridge reverse-proxy
And we run the nginx reverse proxy and the letsencrypt companion on this network, using the
--net reverse-proxy command.
Running the nginx reverse proxy:
docker run -d -p 80:80 -p 443:443 --name nginx-proxy --net reverse-proxy -v $HOME/certs:/etc/nginx/certs:ro -v /etc/nginx/vhost.d -v /usr/share/nginx/html -v /var/run/docker.sock:/tmp/docker.sock:ro --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true jwilder/nginx-proxy
docker run -d --name nginx-letsencrypt --net reverse-proxy --volumes-from nginx-proxy -v $HOME/certs:/etc/nginx/certs:rw -v /var/run/docker.sock:/var/run/docker.sock:ro jrcs/letsencrypt-nginx-proxy-companion
We can then start all our website or other app containers using a
docker-compose.yml file. For example, my docker-compose file looks something like this:
version: '2' services: blog: restart: always image: nginx container_name: blog volumes: - "/etc/nginx/nginx.conf:/etc/nginx/nginx.conf" - "/var/www/blog:/etc/nginx/html" networks: - reverse-proxy environment: - VIRTUAL_PORT=1234 - VIRTUAL_HOST=theconfused.me - LETSENCRYPT_HOST=theconfused.me - [email protected] draggymail: restart: always build: "/var/www/draggymail" container_name: draggymail networks: - reverse-proxy environment: - VIRTUAL_PORT=1234 - VIRTUAL_HOST=draggymail.theconfused.me - LETSENCRYPT_HOST=draggymail.theconfused.me - [email protected] networks: reverse-proxy: external: name: reverse-proxy
The blog service serves up my blog, which is what you’re looking at right now. It just uses the
nginx container. You can insert the nginx configuration by mounting the appropriate configuration file. The format for mounting volumes is
options field is optional, it is where you can specify what docker is allowed to do with the mounted volume.
ro stands for readonly, and
rw gives the docker container permission to (yup, you guessed it) read and write.
The draggymail service builds and runs my NodeJS app. The filepath in
build tells docker to look for the
Dockerfile inside the folder, build the image, and run the container. This is so that I don’t have to build the image separately every time.
Then just run
docker-compose up -d to run your containers.
Handy Docker commands
A few docker commands I found myself repeatedly searching up.
Building an image with a dockerfile in the current directory
docker build -t image_name:tag_name .
Running a docker container
docker run image_name:tag_name
A more complicated command:
docker run -d --name container_name -p 80:80 -p 443:443 --net network_name -v /path/of/file/in/host:/path/of/file/in/container image_name:tag_name
--namespecify the name you want to call this container
--netnetwork to put it on
-vvolumes to mount
Creating a network
docker network create --driver bridge network_name
--driver driver to manage the network
Start and go into interactive mode of last created container
(thanks to this stackoverflow answer)
docker start -a -i `docker ps -q -l`
docker startstart a container (requires name or ID)
-aattach to container
docker psList containers
-qlist only container IDs
-llist only last created container
Start and go into interactive mode of a specific container
docker exec -it container_name_or_id /bin/bash
Remove dangling images
docker rmi $(docker images -qa -f 'dangling=true')
List all containers (running and exited):
docker ps -a