Docker and HTTPS
What is HTTPS
HTTPS stands for Hypertext Transfer Protocol Secure, which is an extension of the HTTP protocol used for secure communication over the internet. It is a way of encrypting the data that is transmitted between a web browser and a web server, making it more difficult for attackers to intercept and steal sensitive information, such as login credentials or credit card numbers.
To enable HTTPS on a website, you need to obtain an SSL (Secure Sockets Layer) certificate. An SSL certificate is a digital certificate that verifies the identity of a website and encrypts the data transmitted between the web server and the client's browser. SSL certificates are issued by trusted certificate authorities (CA), such as Let's Encrypt, Comodo, and Symantec.
There are several ways to get an SSL certificate, depending on your needs and budget. Here are some options:
- Let's Encrypt: Let's Encrypt is a free and open certificate authority that provides SSL certificates for websites. It is widely used and trusted, and can be easily integrated with many web servers, including Apache and Nginx.
- Paid SSL certificates: There are many companies that offer paid SSL certificates, including Comodo, Symantec, and DigiCert. These certificates usually provide a higher level of validation and come with more advanced features, such as extended validation and wildcard certificates.
- Cloud hosting providers: Many cloud hosting providers, such as AWS, Google Cloud, and Azure, offer SSL certificates as part of their hosting packages. These certificates are often managed by the hosting provider, making it easier to install and renew them.
To obtain an SSL certificate, you typically need to generate a certificate signing request (CSR) on your web server, which contains information about your website and your public key. You then submit the CSR to a certificate authority, which will verify your identity and issue a certificate. Once you receive the certificate, you need to install it on your web server and configure your server to use HTTPS.
Keep in mind that SSL certificates have expiration dates and need to be renewed periodically, usually every one or two years. It's also important to ensure that your web server and applications are configured correctly to use HTTPS, and to keep your server and software up to date to address any security vulnerabilities.
Add HTTPS to our Python/Postgres app
Let's take our project from the previous section and add an Nginx service 🤓
Nginx
Nginx is a popular open-source web server that can also function as a reverse proxy, load balancer, and HTTP cache. It is known for its high performance, stability, and ability to handle a large number of simultaneous connections.
Developers should be familiar with Nginx because it is commonly used as a frontend web server in production environments. In addition to its performance benefits, Nginx is also highly customizable and can be used to handle complex routing, authentication, and security configurations.
Nginx also integrates well with many popular web frameworks and technologies, making it a valuable tool for developers who are building web applications. By leveraging Nginx's features, developers can improve the performance, scalability, and security of their applications.
Generate a free ssl certificate
First go to the root of your project and create a new directory call certs
and then run this command :
key.pem
) and a public certificate (cert.pem
) that are valid for 365 days.
Then add execution right to the private key in order to be executed by our nginx service inside our Dockerfile
with the following command :
Create an nginx.conf
file
Go to the root of your project and create a new file called nginx.conf
events {}
http {
upstream app {
server app:8000;
}
server {
listen 80;
listen [::]:80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/ssl/certs/cert.pem;
ssl_certificate_key /etc/ssl/certs/key.pem;
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
We will not dig in detail this script in this course section just make sure to replace yourdomain.com
with your actual domain name, and update the SSL certificate file paths to match your file names and folder locations.
Refactor our docker-compose.yml
file
version: '3'
services:
db:
container_name: db
image: postgres:latest
environment:
POSTGRES_DB: northwind
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- postgresql_bin:/usr/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
- ./northwind.sql:/docker-entrypoint-initdb.d/northwind.sql
- ./files:/files
ports:
- 55432:5432
networks:
- db
pgadmin:
container_name: pgadmin
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: pgadmin4@pgadmin.org
PGADMIN_DEFAULT_PASSWORD: postgres
PGADMIN_LISTEN_PORT: 5050
PGADMIN_CONFIG_SERVER_MODE: 'False'
volumes:
- postgresql_bin:/usr/lib/postgresql
- pgadmin_root_prefs:/root/.pgadmin
- pgadmin_working_dir:/var/lib/pgadmin
- ./files:/files
ports:
- 5050:5050
networks:
- db
app:
build:
context: .
dockerfile: Dockerfile
environment:
DB_HOST: db
depends_on:
- db
ports:
- "8000:8000"
networks:
- db
- mynetwork
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certs:/etc/ssl/certs
networks:
- mynetwork
depends_on:
- app
restart: always
networks:
db:
driver: bridge
mynetwork:
driver: bridge
volumes:
pgadmin_root_prefs:
driver: local
pgadmin_working_dir:
driver: local
postgresql_data:
driver: local
postgresql_bin:
driver: local
Let's talk about the ppart of the docker-compose file defines a service named nginx
that is based on the nginx:latest
Docker image. Here is a detailed explanation of each section:
image: nginx:latest
: This line specifies the Docker image to use for the nginx service, which isnginx:latest
.ports
: This section maps the container ports to the host ports. It exposes the container ports80
and443
to the host machine.volumes
: This section maps the host directories or files to the container directories or files. Here, it mounts thenginx.conf
file from the current directory into the container's/etc/nginx/nginx.conf
path. It also mounts the certs directory from the current directory into the container's/etc/ssl/certs
path.networks
: This section specifies the networks to which this service is attached. In this case, it is attached to the mynetwork network.depends_on
: This section specifies that thenginx
service depends on theapp
service to start. This means that theapp
service will be started before the nginx service.restart
: This line specifies that the container should always be restarted if it stops for any reason.
The networks
section defines two networks: db
and mynetwork
. The networks are bridge driver type
Then you can run docker-compose up -d
and you should see the nginx forwarding our app and all our container like this :
fe86842a56e1 nginx:latest "/docker-entrypoint.…" 19 seconds ago Up 18 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp
d05f1ca65c2f northwind_psql_app "uvicorn app:app --h…" 19 seconds ago Up 18 seconds 80/tcp, 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp northwind_psql_app_1
51553cc3b247 postgres:latest "docker-entrypoint.s…" 9 hours ago Up 19 seconds 0.0.0.0:55432->5432/tcp, :::55432->5432/tcp db
a76abdcbf8da dpage/pgadmin4 "/entrypoint.sh" 9 hours ago Up 19 seconds 80/tcp, 443/tcp, 0.0.0.0:5050->5050/tcp, :::5050->5050/tcp pgadmin
Congrats our app
service is now running in HTTPS 🥳