-Build FastAPI + uvicorn + nginx with docker-compose -Display Web page with FastAPI + uvicorn + Nginx (Templates function by Jinja2)
As a sequel to, I will further edit and add Nginx settings and try to add SSL (HTTPS) and BASIC authentication
Directory structure (excerpt)
$ tree
.
├── app
├── docker-compose.yml
└── web
├── conf.d
│ └── app.conf
└── ssl
├── server.crt
└── server.key
--Fixed docker-compose.yml
--Modify / add files in the web
directory
--Modify conf.d / app.conf
--Preparation of certificate / key (ssl /
directory)
Need each
the detail is right below:
docker-compose.yml
Fixed as follows:
docker-compose.yml
version: '3'
services:
web:
container_name: web
image: nginx:alpine
depends_on:
- app
ports:
- "80:80"
- "${PORT:-8443:443}"
volumes:
- ./web/conf.d:/etc/nginx/conf.d
- ./web/ssl:/etc/nginx/ssl
networks:
- nginx_network
app:
container_name: app
image: test_fastapi_app
build:
context: ./app
dockerfile: Dockerfile
expose:
- 8000
networks:
- nginx_network
# volumes:
# - ./app/app:/app/app
# command: "uvicorn app.main:app --host 0.0.0.0 --proxy-headers --forwarded-allow-ips * --reload"
networks:
nginx_network:
driver: bridge
If you extract only the part where there is a difference,
docker-compose.yml(Excerpt)
services:
web:
ports:
# - "80:80"
- "${PORT:-8443:443}"
volumes:
- ./web/conf.d:/etc/nginx/conf.d
- ./web/ssl:/etc/nginx/ssl
--Changing port mapping for SSL
--Host OS 8443 port (default, set by environment variable) and container (Nginx) 443 port
――It should be noted that using environment variables to set 8443 does not have a deep meaning for personal reasons, so change it as necessary.
-See docker-compose document etc.
--The web / ssl
directory containing the certificate / key is mounted in / etc / nginx / ssl
of the Nginx container.
--The path filename here will also be used later in the Nginx configuration
web / ssl
(key / certificate)web
└── ssl
├── server.crt
└── server.key
Prepare the ones corresponding to server.crt
and server.key
in ↑ and place them in the web / ssl
directory respectively.
In this example, the script (one-liner) that automatically generated the oleore certificate is placed as it is:
make_key.sh
#!/usr/bin/env sh
openssl req -batch -new -x509 -newkey rsa:4096 -nodes -sha256 \
-subj /CN=example.com/O=example -days 3650 \
-keyout ./server.key \
-out ./server.crt
web/conf.d/app.conf
Rewrite the Nginx configuration file.
conf:conf.d/app.conf
upstream backend {
server app:8000;
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
# server_name _;
index index.html index.htm;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Server $http_host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect http:// https://;
proxy_pass http://backend;
}
# log
# access_log /var/log/nginx/access.log;
# error_log /var/log/nginx/error.log;
}
server_tokens off;
Critical changes:
--By rewriting the part that was listen 80
as follows, the key / certificate placed by volume mounting in the container is specified and made HTTPS.
--By the way, the TLS version is also restricted.
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
--Modify / add proxy _ ***
in location /
――I don't remember much about the details because I did it so much and I had a lot of trial and error. .. ..
――So it may be mixed with unnecessary settings. .. ..
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Server $http_host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect http:// https://;
For the time being, with this
docker-compose up -d
If you access https: // localhost: 8443 (port is set by yourself) etc., you can confirm that https communication is enabled.
By the way, I'll apply BASIC authentication
--Generate .htpasswd
in advance
--For example, ʻecho "user:" $ (openssl passwd password) >> /path/to/.htpasswd --The content of
.htpasswditself is the same as Apache httpd etc. --The location is arbitrary to some extent, but this time I placed it in
web / conf.d`:
.
├── app
├── docker-compose.yml
└── web
├── conf.d
| ├── .htpasswd
│ └── app.conf
└── ssl
--Added to web / conf.d / app.conf
:
conf:conf.d/app.conf
upstream backend {
server app:8000;
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
# basic-auth
auth_basic "BASIC AUTH";
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
# server_name _;
index index.html index.htm;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Server $http_host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect http:// https://;
proxy_pass http://backend;
}
# log
# access_log /var/log/nginx/access.log;
# error_log /var/log/nginx/error.log;
}
server_tokens off;
↑ I added the following:
app.conf (additional part)
# basic-auth
auth_basic "BASIC AUTH";
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
--The content of ʻauth_basic may appear as a character string when you are asked to authenticate (maybe it depends on the browser), so rewrite it as appropriate. --ʻAuth_basic_user_file
is loaded by specifying the path of .htpasswd
that is volume mounted in the container.
With this, for example, the authentication can be done as follows:
(* This time it's my certificate, so a warning is issued)
--Nginx reverse proxy settings
--Redirect from http to https with Nginx
--BASIC authentication in Nginx
--Generate .htpasswd
--One-liner of my certificate
Recommended Posts