I have a docker image running a metabase website instance, which I access like: <my-ip>:3000, this image is launched with:
docker run -d -p 3000:3000 \
-v /root/metabase_data:/metabase_data \
-e "MB_DB_FILE=/metabase_data/metabase.db" \
--name metabase metabase/metabase
This access is not secure and I'd like to use it via https, I tried using nginx to add a reverse proxy but I could not find a way to turn this port (or any other for that matter) into https.
Is there a better way to do that?
You can do it with nginx
Wrap your command to docker-compose:
version: '3.7'
services:
nginx:
image: nginx:latest
container_name: nginx
volumes:
- ./nginx:/etc/nginx:ro
ports:
- 80:80
- 443:443
- 3000:3000
restart: always
metabase:
image: metabase/matabase:latest
container_name: metabase
environment:
- MB_DB_FILE=/metabase_data/metabase.db
volumes:
- /root/metabase_data:/metabase_data
restart: always
Create SSL certs for nginx
Write conf for nginx
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream metabase {
server metabase:3000;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
server {
listen 3000 ssl;
ssl_certificate /etc/nginx/ssl/ca.crt;
ssl_certificate_key /etc/nginx/ssl/ca.key;
location / {
proxy_pass http://metabase;
proxy_redirect off;
}
}
}
Execute docker-compose up -d
Related
I'm trying to deploy simple FastAPI app with Docker and Nginx proxy on Google Cloud using simple ssh-terminal window.
My nginx.conf:
access_log /var/log/nginx/app.log;
error_log /var/log/nginx/app.log;
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 128;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header Proxy "";
upstream app_server {
server example.com:8000;
}
server {
server_name example.com;
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /root/ssl/cert.pem;
ssl_certificate_key /root/ssl/key.pem;
location / {
proxy_pass "http://app_server";
}
}
My docker-compose.yml:
version: '3.8'
services:
reverse-proxy:
image: jwilder/nginx-proxy
container_name: reverse-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx:/etc/nginx/conf.d
- ./ssl/cert1.pem:/root/ssl/cert.pem
- ./ssl/privkey1.pem:/root/ssl/key.pem
- ./ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem
networks:
- reverse-proxy
web:
environment: [.env]
build: ./project
ports:
- 8000:8000
command: gunicorn main:app -k uvicorn.workers.UvicornWorker -w 2 -b 0.0.0.0:8000
volumes:
- ./project:/usr/src/app
networks:
- reverse-proxy
- back
networks:
reverse-proxy:
external:
name: reverse-proxy
back:
driver: bridge
After run docker-compose up command and going to example.com address, I get error:
*3 upstream timed out (110: Connection timed out) while connecting to upstream...
Also, I have opened ports with Google Cloud Firewall service (checked with netstat command) and configured my VM's instance with network parameters from this article.
I don't understand why I receive 504 Gateway Time-out cause my service work with the similar configuration on a simple VPS hosting, and also it works from the inside Google Cloud VM's ssh-terminal when using curl and check localhost instead example.com domain. I want to know how to run my service on Google Cloud VM using only docker-compose util for this purpose?
In Nginx config file, try to mention the web container name:
upstream app_server {
server web:8000;
}
My docker compose looks like this:
version: '3.2'
services:
mediawiki:
image: mediawiki:lts
nginx:
image: nginx:stable-alpine
depends_on:
- mediawiki
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
#...
Where mediawiki is a docker container that runs on port 80 in docker and does not appear to have a way to change the port number.
I'm trying to expose mediwiki through ngninx and the nginx config looks like this:
events {
}
http {
server {
listen 80;
location / {
client_max_body_size 2M;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_pass http://mediawiki:80;
}
}
}
Since both nginx and mediawiki is running at port 80, I can't set portmap mediwiki 80:80.
I've tried mapping it to another port under mediawiki such as 7001:80 and in nginx config replace http://mediawiki:80 with http://mediawiki:7001 but this produces bad gateway error when loading the site url at port 80.
How might I fix this?
Let's have a look at reverse proxy in which case I use.
version: '3.2'
services:
mediawiki:
image: mediawiki:lts
nginx:
build: .
image: A_NEW_NAME:VERSION_TAG
depends_on:
- mediawiki
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./wiki.conf:/etc/sites-available/wiki.conf
ports:
- 80:80
This should be your wiki.conf contents:
server {
listen 80;
server_name THE_DOMAIN_NAME_OF_YOUR_MEDIAWIKI;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://mediawiki:80;
proxy_redirect off;
# Socket.IO Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
And add a Dockerfile in the directory where your docker-compose file is:
FROM nginx:stable-alpine
COPY wiki.conf /etc/sites-available/
RUN cd /etc/sites-enabled/ && ln -s /etc/sites-available/wiki.conf
And keep your nginx.conf as default values, or change some values on your own but do not add any directives to serve wiki.
You can replace THE_DOMAIN_NAME_OF_YOUR_MEDIAWIKI wit the actual domain name. Like if you have media.com and your wiki wants to be accessible at wiki.media.com.
Now you can run docker-compose up -d --build and see the result.
Change the service port for media wiki to 8080, like
8080:80
and
Change the nginx port to 7001 inside the local nginx.conf and
proxy_pass http://mediawiki:8080;
./nginx.conf:/etc/nginx/nginx.conf
So, nginx will run on port 7001 and mediawiki on 80.
version: '3.2'
services:
mediawiki:
image: mediawiki:lts
nginx:
image: nginx:stable-alpine
depends_on:
- mediawiki
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:7001
#...
Then access the app at http://mediawiki:80
As the title says, my nginx container is not working as expected unless I restart it. I have several services defined in a docker-compose.yml file that looks like this: reverseproxy is my nginx container, and service-a and service-b are Node.js servers.
version: "3.4"
services:
reverseproxy:
container_name: reverseproxy
build:
context: ./proxy
ports:
- "80:80"
service-a:
container_name: service-a
build:
context: ./service-a
ports:
- "3500:3500"
command: ["yarn", "run", "watch-debug"]
service-b:
container_name: service-b
build:
context: ./service-b
ports:
- "3501:3501"
command: ["yarn", "run", "watch-debug"]
The Dockerfile used to build my reverseproxy service simply removes the default.conf file and then copies the nginx.conf file from my host to the image:
FROM nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/nginx.conf
And my nginx.conf file that gets copied into the image looks like this:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 80;
location /api/customers {
proxy_pass http://service-a:3500;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location /api/products {
proxy_pass http://service-b:3501;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
When I docker-compose up everything spins up fine, but when I POST to one of my endpoints (for example, localhost:80/api/customers) then nginx responds with a 502. But if I docker container stop reverseproxy and then docker container start reverseproxy, then everything works as expected and I'm able to hit my endpoints with localhost:80.
I was able to docker exec -it reverseproxy /bin/sh and was able to verify that default.conf is gone and nginx.conf was copied over from my host as expected. I have followed the sample configuration from the nginx page on Docker Hub and most tutorials online show a nearly identical set up.
What may be causing this? How could make my nginx revereproxy service work as expected without restarting the container?
Edit: I am using Postman to make my requests localhost:80
#DavidMaze had the correct solution -- thank you!
reverseproxy:
container_name: reverseproxy
build:
context: ./proxy
ports:
- "80:80"
depends_on:
- "service-a"
- "service-b"
Makes sense that it only works as expected on a restarted because the other services were available by then. Just tried it out and it works as expected.
This is my docker-compose file.
version: "3.7"
services:
foo01:
shm_size: "1000000000"
build:
context: ./foo
tty: true
volumes:
- "./foo/src:/tmp/"
foo02:
shm_size: "1000000000"
build:
context: ./foo
tty: true
volumes:
- "./foo/src:/tmp/"
nginx:
build: ./nginx
tty: true
links:
- foo01
- foo02
ports:
- "80:80"
And this is my nginx conf file if it's needed.
events { worker_connections 1024; }
http {
proxy_headers_hash_max_size 1024;
proxy_headers_hash_bucket_size 64;
upstream TestApp {
# References to our app containers, via docker compose
server foo01:5000;
server foo02:5000;
}
server {
listen 80;
server_name domain.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
# proxy_redirect off;
proxy_buffers 8 24k;
proxy_buffer_size 4k;
proxy_pass http://TestApp;
proxy_set_header Host $host;
}
}
}
My question is, once I build and run docker-compose, how do I check if foo01:5000 is reachable from my nginx docker container? Is it possible to communicate from the bash shell of a docker?
You could open the bash of a docker container as fallow
docker exec -it <CONTAINER_ID> bash
And execute a curl command to other container, if you have curl in your container, otherwise you have to install it
curl foo01:5000
But I think the problem is in the docker-compose.yml file, you didn't specified the port 5000 for foo01 and expose it.
I am trying to setup SSL for my homepage (www.myhomepage.com) using LetsEncrypt on a nginx reverse-proxy. I have an additional host without SSL running for testing proxying to multiple hosts (www.myotherhomepagewithoutssl.com).
The reverse-proxy and two hosts are running in three separate docker containers.
I got both hosts to work without SSL, but the encrypted one does not work, when trying to use SSL. The LetsEncrypt certificates appear to be setup/obtained correctly and are persisted in a docker volume.
I am trying to follow and adapt this tutorial to setup the LetsEncrypt SSL encryption:
http://tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no-downtime/
When trying to connect to the SSL encrypted host under www.myhomepage.com using Firefox I get this error:
Unable to connect
The other non-encrypted host under www.myotherhomepagewithoutssl.com works. And as I stated above, when I have www.myhomepage.com setup without SSL (in the same way as www.myotherhomepagewithoutssl.com), it is also reachable.
My complete setup is listed below and consists of:
* reverse_proxy_testing.sh: Bash script to clean-up, build and start the containers.
* compose_reverse_proxy.yaml: Docker-Compose file.
* reverse_proxy.docker: Dockerfile for setting up the reverse-proxy with nginx.
* nginx.conf: nginx config-file for the reverse-proxy.
I suspect that my error is located somewhere inside nginx.conf, but I cannot find it.
Any help is much appreciated!
nginx.conf:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
server {
deny all;
}
upstream myhomepage {
server myhomepage_blog:80;
}
upstream docker-apache {
server apache:80;
}
server {
listen 80;
listen [::]:80;
server_name www.myhomepage.com myhomepage.com;
return 302 https://$server_name$request_uri;
}
server {
listen 443 ssl;
listen [::]:443;
server_name www.myhomepage.com myhomepage.com;
ssl_certificate /etc/letsencrypt/live/myhomepage.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myhomepage.com/privkey.pem;
location /.well-known {
root /var/www/ssl-proof/myhomepage.com/;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://myhomepage;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 900s;
}
}
server {
listen 80;
server_name www.myotherhomepagewithoutssl.com myotherhomepagewithoutssl.com;
location / {
proxy_pass http://docker-apache;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
reverse_proxy.docker:
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
RUN mkdir -p /var/www/ssl-proof/myhomepage.com/.well-known
RUN apk update && apk add certbot
compose_reverse_proxy.yaml:
version: '3.3'
services:
reverseproxy:
image: reverseproxy
ports:
- 80:80
restart: always
volumes:
- proxy_letsencrypt_ssl_proof:/var/www/ssl-proof
- proxy_letsencrypte_certificates:/etc/letsencrypt
apache:
depends_on:
- reverseproxy
image: httpd:alpine
restart: always
myhomepage_blog:
image: wordpress
links:
- myhomepage_db:mysql
environment:
- WORDPRESS_DB_PASSWORD=somepassword
- VIRTUAL_HOST=myhomepage.com
volumes:
- myhomepage_code:/code
- myhomepage_html:/var/www/html
restart: always
myhomepage_db:
image: mariadb
environment:
- MYSQL_ROOT_PASSWORD=somepassword
- MYSQL_DATABASE=wordpress
volumes:
- myhomepage_dbdata:/var/lib/mysql
restart: always
volumes:
myhomepage_dbdata:
myhomepage_code:
myhomepage_html:
proxy_letsencrypt_ssl_proof:
proxy_letsencrypte_certificates:
reverse_proxy_testing.sh:
#!/bin/bash
docker rm testreverseproxy_apache_1 testreverseproxy_myhomepage_blog_1 testreverseproxy_myhomepage_db_1 testreverseproxy_reverseproxy_1
docker build -t reverseproxy -f reverse_proxy.docker .
docker-compose -f reverse_proxy_compose.yml up