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.
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.