dockernginxdocker-composelets-encryptcertbot

Nginx in docker does not find certificate file I shared the volume with docker compose


I have one Golang project and two React projects. I want to serve them from the same EC2 on which 3 different domains are pointed (stage.mysite.com, stage.admin.mysite.com, and stage.user.mysite.com).

I want to serve them with docker. Here is my docker-compose file:

./deploy/compose/docker-compose.yml

version: '3.8'

services:
  postgresd:
    # code for postgres docker

  api:
    container_name: api
    depends_on:
      - postgresd
    build:
      context: ../..
      dockerfile: deploy/compose/Dockerfile
    env_file:
      - ../../.env
    labels:
      logging: "promtail"
    ports:
      - "${WEB_APP_PORT}:4000"
    restart: on-failure
    networks:
      main:

  nginx:
    container_name: app-nginx
    image: nginx:alpine
    env_file:
      -  ../../.env
    ports:
      - "${NGINX_PORT}:80"
      - "${NGINX_SSL_PORT}:443"
    restart: on-failure
    networks:
      main:
    depends_on:
      - asuntogo-api
    volumes:
      - ./nginx/:/etc/nginx/conf.d/
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
      - ./admin-fe/:/var/www/admin-fe
      - ./user-fe/:/var/www/user-fe
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

  certbot:
    image: certbot/certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

volumes:
  pgdata:

networks:
  main:

Here is my deploy file tree:

deploy
└── compose
    ├── Dockerfile # docker file for golang app
    ├── admin-fe # admin frontend build files
    ├── docker-compose.yml
    ├── nginx
    │   └── app.conf
    └── user-fe # user frontend build files

app.conf

server {
    listen 80;
    server_name stage.mysite.com www.stage.mysite.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name stage.mysite.com www.stage.mysite.com;

    ssl_certificate /etc/letsencrypt/live/stage.mysite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/stage.mysite.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://api:4000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location /api/health {
        access_log off;
        add_header 'Content-Type' 'application/json';
        return 200 '{"status":"UP"}';
    }
}

server {
    listen 80;
    server_name stage.admin.mysite.com www.stage.admin.mysite.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name stage.admin.mysite.com stage.admin.mysite.com;

    ssl_certificate /etc/letsencrypt/live/stage.admin.mysite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/stage.admin.mysite.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    charset utf-8;
    root    /var/www/admin-fe;
    index   index.html;

    location / {
        root /var/www/admin-fe;
        try_files $uri  /index.html;
    }
    error_log  /var/log/nginx/admin-fe-error.log;
    access_log /var/log/nginx/admin-fe-access.log;
}

server {
    listen 80;
    server_name stage.user.mysite.com www.stage.user.mysite.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name stage.user.mysite.com www.stage.user.mysite.com;

    ssl_certificate /etc/letsencrypt/live/stage.user.mysite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/stage.user.mysite.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    charset utf-8;
    root    /var/www/user-fe;
    index   index.html;

    location / {
        root /var/www/user-fe;
        try_files $uri  /index.html;
    }
    error_log  /var/log/nginx/user-fe-error.log;
    access_log /var/log/nginx/user-fe-access.log;
}

I created certificates using the following command for all of my domains:

sudo certbot certonly --standalone --preferred-challenges http -d example.com

after created the certificates I move then into deploy/compose/certbot/ folder. So I have certificate presented in deploy/compose/certbot/conf/live/ and shared the volume in nginx docker compose.

when I try to run docker compose up --build it gives the following error:

app_nginx | nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/stage.admin.mysite.come/fullchain.pem": BIO_new_file() failed (SSL: error:80000002:system library::No such file or directory:calling fopen(/etc/letsencrypt/live/stage.admin.mysite.come/fullchain.pem, r) error:10000080:BIO routines::no such file)

How can I solve this problem? I am very new at nginx. Thanks in advance.


Solution

  • After trying a couple of times I have successfully deployed every app.

    Here is the approach I have followed.

    The error message shows that Nginx cannot find the create certificate in the mentioned path. So I have tried to create the certificate manually in the certbot folder using my docker container certbot servicer.

    Here is the command I ran in my EC2 before the docker build.

    sudo docker-compose run --rm --entrypoint "\
      certbot certonly --webroot -w /var/www/certbot \
        --email aemail@mail.com \
        -d your-domain.com \
        --rsa-key-size 4096 \
        --agree-tos \
        --force-renewal" certbot
    

    This command created the certificate in deploy/compose/certbot/conf/live

    I do it for all of my domains. Then I run sudo docker compose up --build and It works fine.

    Note: Also clean my docker volume for nginx.