Easily add https and multiple apps on a vps using Docker

  • Vps
  • Docker
  • nginx-proxy
  • Let's Encrypt

It’s been a long time since my last post, but I had my first child (Coline) less than a week after it. I first thought I’d be able to manage both, but it’s clearly not possible or if you guys have tips just let me know !

Everybody now knows Docker and how awesome it is, so I won’t go into much details about it (as it’s not the purpose of this post) but I will describe how I am using it to add https and multiple apps on a basic vps.

This example is based on how I am running this website and my parent’s one on the same vps.


First of all you need :

  • A Vps
  • Docker
  • Whathever you want as websites or apps that use docker. In our example we will use two images :
    • An Express hello-world in a node:alpine based image.
    • A React hello-world (using create-react-app) in a nginx:alpine based image.

Installing / Getting started

This post will assume that you know how to init and use a server, so once you have Docker up and running on your server, don’t forget to add it to your user group to avoid doing sudo each time you want to use a docker command :

sudo usermod -aG docker $USER

Now you can pull the images you want or simply let Docker pull those present in your docker-compose.yml if they are not already in your server.

I mostly use alpine based images because they are very lightweight !!

So now you can set up your docker-compose.yml as the one bellow :

version: '2'
    image: jwilder/nginx-proxy:alpine
    container_name: nginx-proxy
    restart: unless-stopped
      - 80:80
      - 443:443
      - /srv/docker/nginx/certs:/etc/nginx/certs:ro
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro

    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nginx-proxy-companion
    restart: unless-stopped
      - /srv/docker/nginx/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock
      - nginx-proxy

    image: rcauquil/react-helloworld
    container_name: react-helloworld
    restart: unless-stopped
      - VIRTUAL_HOST=yourhostname.tld

    image: rcauquil/express-helloworld
    container_name: express-helloworld
    restart: unless-stopped
      - 3000
      - VIRTUAL_HOST=yourhostname.tld
      - LETSENCRYPT_HOST=yourhostname.tld
      - LETSENCRYPT_EMAIL=your@email.tld

Nothing fancy here, we are simply following both usage of nginx-proxy and nginx-proxy-companion unless we are adding a restart: unless-stopped policy to our containers.


This part only contains the VIRTUAL_HOST env from nginx-proxy, so our app will only have http support.


In this part we are adding two more env LETSENCRYPT_HOST and LETSENCRYPT_EMAIL to make use of Let’s Encrypt and have https support to our app.

nginx-proxy-companion will take care of the automatic creation/renewal of Let’s Encrypt certificates and support creation of Multi-Domain (SAN) Certificates.

I have to specify which port I want my container to expose, 3000 in this example (default one in express) because I did not specified it in the Dockerfile while building the image.

I didn’t have to do it in the previous part because the nginx image I am using to serve my react app, exposes on port 80.


Now you can simply start all your containers :

docker-compose up -d

If you want to stop a specific container to update it without having to shut down all your running containers :

docker-compose stop express-helloworld

Then to run it again :

docker-compose up -d express-helloworld

You can add the –force-recreate flag to clear the cache and avoid useless headaches.

If you want to stop all of your running containers :

docker-compose down


This is a very basic example of how to use nginx-proxy and nginx-proxy-companion to run and easily add https on your apps, but I hope it will help some of you !