HTTPS for Local Docker: Setting Up a Pro “Green Padlock” with mkcert and Nginx

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

Coding on http://localhost:3000 or 8080 is usually straightforward. But things start to get complicated when you need to test OAuth2, Service Workers, or receive Webhooks from third parties. At this point, the lack of “real” SSL on your local machine not only makes the browser show red warnings but also causes APIs to flatly reject connections.

In the past, I used OpenSSL to self-sign certificates. The most annoying part was having to click through several layers of Chrome’s “Your connection is not private” warnings every time I accessed the site. Later, when working on larger projects, I switched to the combo of mkcert + Nginx Reverse Proxy. This method is clean, professional, and most importantly, turns “green” immediately.

The Issue: Why You Shouldn’t Use http://localhost?

There are 3 practical reasons why I always recommend setting up HTTPS from the start:

  • Match Production: Avoid “Mixed Content” errors when deploying. Specifically, Cookie attributes like Secure or SameSite=None require HTTPS to function.
  • Specific Features: Geolocation, Push Notifications, or modern frameworks like Next.js often require a Secure Context.
  • Psychology: Seeing the green padlock in the address bar provides a sense of security and feels much more professional while working.

In fact, I once spent an entire afternoon debugging an issue where sessions weren’t being maintained after a redirect from the Stripe payment gateway. It turned out the cause was simply because the local cookie was missing the Secure flag – something that is mandatory by default in real HTTPS environments.

Required Tools

To get started, you’ll need:

  1. Docker & Docker Compose: The standard application packaging tools.
  2. mkcert: The “magic” that helps create a trusted Local CA with just one command.
  3. Nginx: Acts as the “gatekeeper” (Reverse Proxy) to receive HTTPS traffic and distribute it to containers.

Installing mkcert

If you’re using macOS, you can install it via Homebrew:

brew install mkcert
brew install nss # Required if you use Firefox

For Windows, use Chocolatey:

choco install mkcert

After installation, run the following command to register the Local CA with your system. You only need to do this once on your computer:

mkcert -install

Hands-on: Setting Up HTTPS for a Docker Project

Suppose you have an application running on port 8080 and want to access it via the virtual domain itfromzero.test.

Step 1: Create SSL Certificates

In your project directory, create a folder to store the certificates:

mkdir -p certs
mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem itfromzero.test "*.itfromzero.test" localhost 127.0.0.1

Now, the certs folder will contain two .pem files. Note: Never commit the key file to Git to ensure security.

Step 2: Configure Nginx as a Reverse Proxy

Create an nginx.conf file to route traffic:

server {
    listen 80;
    server_name itfromzero.test;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name itfromzero.test;

    ssl_certificate /etc/nginx/certs/local-cert.pem;
    ssl_certificate_key /etc/nginx/certs/local-key.pem;

    location / {
        proxy_pass http://web_app:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Step 3: Docker Compose File

This is where we connect everything. We will mount the certificate and config files into the Nginx container.

version: '3.8'

services:
  web_app:
    image: nginx:alpine
    # Your app is listening on port 8080
    command: ["nginx", "-g", "daemon off;"]

  nginx_proxy:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - web_app

Step 4: Configure the Hosts File

Since the domain itfromzero.test isn’t real, you need to “trick” your computer into pointing this domain to your local IP.

Open the /etc/hosts file (Linux/macOS) or C:\Windows\System32\drivers\etc\hosts (Windows) and add the line:

127.0.0.1 itfromzero.test

Verifying the Results

Start the system with the familiar command:

docker-compose up -d

Now, open your browser and go to https://itfromzero.test. You should see the green padlock appear immediately without having to click any security confirmation buttons.

Tips to Avoid “Silly” Mistakes

Here are 3 common points where people often stumble:

  • File Permissions: On Linux, if Nginx reports it cannot read the certs, try chmod 644 certs/* to reset the permissions.
  • Service Name: The proxy_pass in Nginx must exactly match the service name you defined in docker-compose.yml.
  • DNS Cache: If you edited the hosts file but it’s not taking effect, try flushing your DNS or restarting your browser to update.

Conclusion

Using mkcert makes local development much more professional. You no longer have to fiddle with separate SSL configurations for every framework or language. With a single Nginx gateway, every project gets proper HTTPS. Good luck with your setup!

Share: