Run Docker image on a different host - docker

Is it possible to run docker image on other host than localhost?
Ports 80 and 443 are always occupied by other applications, so I was wondering if it's possible to run it on, e.g. 192.168.0.100, and then set up the /etc/hosts file to assign a name for that IP address.
I was trying to set up extra_hosts option, but I'm not sure if it's meant for that. Either way, I did not succeed with setting it up as there was some issue with Value should be a mapping, not an array.
I guess it's worth mentioning that I'm on macOS using docker-compose to run everything. Thank you in advance.
docker-compose.yaml
version: "2"
services:
php:
build: ./php
volumes:
- ../develog.org:/usr/share/nginx/html
depends_on:
- memcached
nginx:
build: ./nginx
ports:
- 4001:80
- 4002:443
volumes_from:
- php:ro
depends_on:
- php
memcached:
image: memcached:alpine
networks:
default:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.1.0.0/16
nginx configuration
map $scheme $ssl_request {
https "https";
}
server {
# support http and ipv6
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
# support https and ipv6
listen 443 default_server ssl;
listen [::]:443 ipv6only=on default_server ssl;
# path to web directory
root /web/;
index index.html index.htm;
# domain or subdomain
server_name localhost;
include self-signed.conf;
include ssl-params.conf;
}

Why not use a different port when running your image? (unless you have to use port 80/443)
So, for example, if you are running a webserver image like Apache httpd, which normally runs on port 80 use:
docker run -p 127.0.0.1:8080:80/tcp httpd
Then you can just use port 8080 on localhost.
For docker-compose add a ports section to the docker-compose.yaml file. E.g.
image: <image>
ports:
- "8080:80"
The actual ports/image would depend on which image you are using.
See https://docs.docker.com/compose/compose-file/#ports for details.

Related

Deploying a Docker container with Nginx and FastAPI on Google Cloud Platform from SSH-term

I have a some issue when trying to deploy a simple FastAPI application with Nginx on Google Cloud Platform. In my case I should use SSH-terminal to run Docker container with Nginx and FastAPI. My nginx.conf configuration looks like:
access_log /var/log/nginx/app.log;
error_log /var/log/nginx/app.log;
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://example.com:8004/";
}
}
And my docker-compose.yml looks like:
version: '3.8'
services:
nginx-proxy:
image: nginx
container_name: nginx-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
web:
environment: [.env]
build: ./project
ports:
- 8004:8000
command: gunicorn main:app -k uvicorn.workers.UvicornWorker -w 2 -b 0.0.0.0:8000
volumes:
- ./project:/usr/src/app
networks:
default:
external:
name: nginx-proxy
Also, I have a Google Cloud VM instance with Firewall HTTP, HTTPS traffic On option, and additionally configured Firewall with rules allowed TCP connections over 443 and 80 ports (Domain name is provided by Google Cloud also, and redirects to VM's external IP address when I put it in my browser address field).
I run my docker-image from SSH-terminal with docker-compose up --build, then I get 502 Bad Gateway Nginx error in my browser (after going to example.com). I would like to know whether it is possible to run the docker image this way from inside SSH-terminal, as well as which steps did I miss to do it the right way?

Running Nginx behind Traefik, problem with ports different than 80

I want to run Nginx as static file server behind Traefik reverse proxy using Docker (docker-compose).
docker-compose.yml
version: '3.8'
services:
traefik:
image: traefik
command:
- --entrypoints.web.address=:80
- --providers.docker
- --providers.docker.exposedbydefault=false
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
nginx:
build: ./docker/dev/nginx/.
labels:
- traefik.enable=true
- traefik.http.routers.nginx.entrypoints=web
- traefik.http.routers.nginx.rule=PathPrefix(`/static`) || PathPrefix(`/media`) || Path(`/robots.txt`) || Path(`/favicon.ico`)
- traefik.http.services.nginx.loadbalancer.server.port=80
nginx.conf
server {
listen 80;
listen [::]:80;
...
}
And it works,
But when I try to change internal nginx port to another, lets say 8082, Traefik returns 502 error and prints '502 Bad Gateway' caused by: dial tcp 172.21.0.6:8082: connect: connection refused" in debug logs.
By changing port I mean:
replacing traefik.http.services.nginx.loadbalancer.server.port=80 with traefik.http.services.nginx.loadbalancer.server.port=8082 in docker-compose.yml
replacing listen 80; listen [::]:80; with listen 8082; listen [::]:8082; in nginx.conf
I have other apps in config, like Django running on gunicorn server. There is no problem for gunicorn to listen on 3000 port, and for Traefik to forward incoming :80 requests to :3000.
Why doesn't it work with nginx?
You have told nginx to listen to 8082 port which is ok, but the container has to expose the port. (I guess by default the container expose 80 port)
You seem to have a custom nginx image, so you can add/replace the EXPOSE keyword in your image to have something like this : EXPOSE 8082.
You have to build and restart the container for the change to take effect, then you can check the exposed ports with docker-compose ps.

Docker compose & nginx network hostnames

I have the following configuration:
nginx started by a docker compose file acting as reverse proxy // ssl endpoint
an application service started by a different docker compose (for modularity reasons) file serving a application
reverse_proxy and app_service are connected via the app_network
Since they are connected via the app_network, I am able to address the app_service in the nginx configuration like http://app_service:8080, which is nice because I don't need to expose ports on the app service itself.
Unfortunately, nginx won't start until I brought up the app service container because it checks the existance of the hostname app_service upon startup.
How can I prevent nginx from checking the hostname on startup, maybe causing a Bad Gateway error when trying to connect while app_service is not running yet?
Configuration files for reference:
# reverse proxy docker-compose.yml
version: '3'
services:
reverse_proxy:
restart: always
container_name: reverse_proxy
image: nginx
ports:
- 80:80
- 443:443
volumes:
- /srv/docker/nginx/config:/etc/nginx
- /srv/ssl:/srv/ssl
networks:
default:
external:
name: app_network
# application service docker-compose.yml
version: '3'
services:
app_service:
restart: always
container_name: app_service
image: <my_app_image>
networks:
default:
external:
name: app_network
# nginx config
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name app.example.com;
location / {
proxy_pass http://app_service:8080;
include proxy.conf;
}
ssl_certificate /srv/ssl/<mycert>.crt;
ssl_certificate_key /srv/ssl/<mykey>.key;
}
Here is a way that worked for me:
# nginx config
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name app.example.com;
location / {
set $upstream app_service:8080;
proxy_pass $upstream;
include proxy.conf;
}
ssl_certificate /srv/ssl/.crt;
ssl_certificate_key /srv/ssl/.key;
}
This results in a 502 Bad Gateway message if the host is unavailable and does not check availability at startup.

Nginx reverse proxy (in Docker) to a web app (also in Docker)

I have set up a web application in docker which is currently running internal to the host at 172.19.0.3:8888. I want this web application accessible over the internet on port 443 (https), with requests to port 80 (HTTP) redirected to 443.
I plan to use an Nginx reverse proxy in a docker container to achieve this, but I do not know how to properly configure it to point at the docker container 172.19.0.3:8888. Accessing http://172.19.0.3:8888 from the host works.
Here is the guide I tried to follow, but it just didn't show how to point at a docker container specifically.
https://medium.com/#pentacent/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71
Note
If I set the port 443 proxy_pass to http://example.org, it works. So Cert configurations are working correctly.
Web application
Running on 172.19.0.3:8888 internal to the host
docker-compose for Nginx and Certbot
My certs are coming back clean.
version: '3'
services:
nginx:
image: nginx:1.15-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Volumes/nginx:/etc/nginx/conf.d
- ./Volumes/certbot/conf:/etc/letsencrypt
- ./Volumes/certbot/www:/var/www/certbot
certbot:
image: certbot/certbot
volumes:
- ./Volumes/certbot/conf:/etc/letsencrypt
- ./Volumes/certbot/www:/var/www/certbot
Nginx app.conf
server {
listen 80;
server_name forums.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name forums.example.com;
ssl_certificate /etc/letsencrypt/live/forums.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/forums.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://172.19.0.3:8888/;
}
}
Web Application
flarum:
image: mondedie/docker-flarum:0.1.0-beta.8.1-stable
container_name: flarum
env_file:
- ./flarum.env
volumes:
- ./Volumes/assets:/flarum/app/public/assets
- ./Volumes/extensions:/flarum/app/extensions
- ./Volumes/nginx:/etc/nginx/conf.d
depends_on:
- mariadb
mariadb:
image: mariadb:10.2
container_name: mariadb
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=flarum
- MYSQL_USER=flarum
- MYSQL_PASSWORD=password
volumes:
- ./Volumes/mysql/db:/var/lib/mysql
Docker Compose creates a seprate network for docker-compose.yaml file.
So you can add your web application as service (eg: webapp) in current compose file. And in nginx.conf directly point to your service. Rather than using IP you can use the service name as DNS which will resolve by Docker for the same network.
location / {
proxy_pass http://webapp:8888/;
}

How do I use a different port for an nginx proxy on docker?

I have an two containers running via docker-compose:
version: '3'
services:
web:
image: me/web
container_name: web
nginx:
image: me/nginx
container_name: nginx
ports:
- '80:80'
volumes:
- ../nginx:/etc/myapp/nginx
My nginx container copies in a new default.conf from the mapped volume from the entrypoint.sh:
#!/usr/bin/env bash
cp /etc/myapp/nginx/default.conf /etc/nginx/conf.d/default.conf
nginx -g 'daemon off;'
My custom default.conf looks like:
server {
listen 80;
server_name my.website.com;
location / {
proxy_pass http://web/;
}
}
With this configuration everything works as expected. After starting with docker-compose I can then navigate to http://my.website.com and access the web container instance properly.
However, now I want to change my port to something other than the default 80, such as 81 for example:
services:
..
nginx:
image: me/nginx
container_name: nginx
ports:
- '81:80'
..
Now this no longer works. Whenever I visit http://my.website.com:81 I get:
This site can’t be reached
my.website.com refused to connect.
ERR_CONNECTION_REFUSED
The other weird part is that if I use localhost rather than my.website.com, everything works just fine on port 81. Ex:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web/;
}
}
Navigating to http://localhost:81 works correctly.
What am I doing wrong here? How do I configure nginx to something other than localhost (my domain) and proxy on a different port than 80 to my web container?
Check that port 81 is open on my.website.com i.e. check firewall rules are in place etc

Resources