By A Zaker
Okay so I’m learning Docker and I am trying to deploy a test app with a subdomain (who’s domain was bought from another provider) which is pointing to my server. The server already has non-dockerized Nginx setup which serves couple of other non-dockerized apps perfectly. And that part means Nginx is already using port 80 and 443. And the subdomain somehow shows Nginx default page when visited. This is my server situation. Now let me explain what happens with the dockerized app.
The app is using 4 images to create 4 containers: Nodejs, Mongodb, Nginx and Certbot. Before adding Certbot, I could perfectly access the app with <server-ip>:<port>. But now I need to attach that subdomain (test.example.dev) to my app with Let’s Encrypt SSL certificates.
So after the build is done with Docker Compose, I see that Nginx and Certbot is exited with errors.
This is my nginx/default.conf file:
server {
listen 80;
listen [::]:80;
server_name test.example.dev;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://test.example.dev$request_uri;
}
}
server {
listen 443 default_server ssl http2;
listen [::]:443 ssl http2;
server_name test.example.dev;
ssl_certificate /etc/nginx/ssl/live/test.example.dev/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/test.example.dev/privkey.pem;
location /api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://practice-app:3050;
proxy_redirect off;
}
}
Here’s my shared docker-compose file for both dev and prod environment:
version: '3'
services:
practice-app:
build: .
depends_on:
- mongo
nginx:
image: nginx:stable-alpine
ports:
- "4088:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- practice-app
mongo:
image: mongo:4.4.6
environment:
- MONGO_INITDB_ROOT_USERNAME=test
- MONGO_INITDB_ROOT_PASSWORD=test
volumes:
- mongo-db:/data/db
volumes:
mongo-db:
And here’s my docker-compose.prod.yml file:
version: "3"
services:
practice-app:
build:
context: .
args:
NODE_ENV: production
environment:
- NODE_ENV=production
command: node index.js
nginx:
ports:
- "4088:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./certbot/www:/var/www/certbot/:ro
- ./certbot/conf/:/etc/nginx/ssl/:ro
certbot:
image: certbot/certbot:latest
volumes:
- ./certbot/www/:/var/www/certbot/:rw
- ./certbot/conf/:/etc/letsencrypt/:rw
depends_on:
- nginx
mongo:
environment:
- MONGO_INITDB_ROOT_USERNAME=test
- MONGO_INITDB_ROOT_PASSWORD=test
Nginx logs says:
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/01/31 13:42:28 [emerg] 1#1: cannot load certificate "/etc/nginx/ssl/live/test.example.dev/fullchain.pem": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/nginx/ssl/live/test.example.dev/fullchain.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)
nginx: [emerg] cannot load certificate "/etc/nginx/ssl/live/test.example.dev/fullchain.pem": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/nginx/ssl/live/test.example.dev/fullchain.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)
And Certbot logs says:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Certbot doesn't know how to automatically configure the web server on this system. However, it can still get a certificate for you. Please run "certbot certonly" to do so. You'll need to manually configure your web server to use the resulting certificate.
But after adding the following code:
command: certonly --webroot -w /var/www/certbot --force-renewal --email example@gmail.com -d test.example.dev --agree-tos
under certbot service, the log changed to this:
[17:00] [server1.com test] # docker logs test_certbot_1
Saving debug log to /var/log/letsencrypt/letsencrypt.log Skipped user interaction because Certbot doesn't appear to be running in a terminal. You should probably include --non-interactive or --force-interactive on the command line.
Account registered.
Requesting a certificate for test.example.dev
Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
Domain: test.example.dev
Type: unauthorized
Detail: Invalid response from http://test.example.dev/.well-known/acme-challenge/J7_MZAg5yYLi3P_VVEalOwlU5cH3NAmevlhTKCvt6Zo [xx.xx0.xxx.7x]: "<html>\r\n<head><title>404 Not Found</title></head>\r\n<body>\r\n<center><h1>404 Not Found</h1></center>\r\n<hr><center>nginx</center>\r\n"
Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.
Some challenges have failed. Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
What am I doing wrong here? Please give me a beginner friendly solution as I am new to DevOps.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hello,
The issue you’re facing involves multiple aspects, including Nginx configuration, Docker Compose setup, and Certbot SSL certificate generation. Let’s address these step by step to get your setup working.
Nginx and Certbot Containers Exiting: Your Nginx container tries to start before the SSL certificates are available, causing it to exit because it can’t find the specified certificate files. Similarly, Certbot is having trouble validating your domain because it cannot place the challenge files in a location where they can be served by Nginx due to incorrect or insufficient configuration.
Port Conflicts: You mentioned that the server already has a non-Dockerized Nginx instance running on ports 80 and 443. This setup will conflict with any Docker containers trying to bind to the same ports. Since you’re mapping port 4088 to 80 for Nginx inside Docker, ensure external requests to your domain on port 80/443 are correctly routed to port 4088 of your Dockerized Nginx.
Domain Validation Failed: Certbot is unable to validate your domain because the ACME challenge requests from Let’s Encrypt are not reaching the /.well-known/acme-challenge/ location served by your Dockerized Nginx.
Since your server’s primary Nginx instance is already using ports 80 and 443, you need to ensure it forwards ACME challenge requests to your Dockerized Nginx:
location /.well-known/acme-challenge/ {
proxy_pass http://localhost:4088;
}
docker-compose.prod.yml and assign it to both services.networks:
default:
name: my_network
command: >
sh -c "sleep 10 &&
certonly --webroot -w /var/www/certbot --force-renewal --email example@gmail.com -d test.example.dev --agree-tos --non-interactive"
The sleep 10 command is a simple way to wait for Nginx to be up. Adjust the sleep duration as necessary.
ssl_certificate /etc/nginx/ssl/dummy.crt;
ssl_certificate_key /etc/nginx/ssl/dummy.key;
Generate dummy certificates or place any temporary certificate files at the paths specified in your Nginx configuration, and update the paths to the real certificates once Certbot has successfully obtained them.
./certbot/www/ and ./certbot/conf/) are writable by the Certbot container and readable by the Nginx container. This ensures Certbot can write the challenge files and certificates where Nginx expects them.After addressing these points, redeploy your Docker Compose setup. Ensure that the ACME challenge requests can reach your Dockerized Nginx, and that Certbot can successfully validate your domain and obtain certificates.
Best,
Bobby
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.