Exposing local dockerised app using nginx docker container - docker

I have a julia app which has been dockerized using below docker file. And,I am running this local app as docker container on port 8080. The goal is to expose this docker app (port 8080) to public using nginx docker container.
I have followed this tutorial: https://www.domysee.com/blogposts/reverse-proxy-nginx-docker-compose and based on the instructions I have created two files, docker-compose.yml and nginx.conf as shown below.
Dockerfile for the local-app:
FROM julia:1.6
RUN apt-get update && apt-get install -y gcc
ENV JULIA_PROJECT #.
WORKDIR /home
ENV VERSION 1
ADD . /home
EXPOSE 8080
ENTRYPOINT ["julia", "-JApp.so", "-t", "auto", "-L", "src/App.jl", "-e", "App.run()"]
Docker-Compose:
version: "3.9"
services:
nginx:
image: nginx:alpine
container_name: production_nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- .:/usr/share/nginx/html
- ./nginx/error.log:/etc/nginx/error_log.log
- ./nginx/cache/:/etc/nginx/cache
- /etc/letsencrypt/:/etc/letsencrypt/
ports:
- 8080:80
- 443:443
local-app:
image: local-app:latest
container_name: production-local-app
expose:
- "8080"
Nginx.conf:
events {
}
http {
error_log /etc/nginx/error_log.log warn;
client_max_body_size 20m;
proxy_cache_path /etc/nginx/cache keys_zone=one:500m max_size=1000m;
server {
server_name app.local.hosting;
location /local-app {
proxy_pass http://localhost:8080;
rewrite ^/local-app(.*)$ $1 break;
}
listen 80;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/app.local.hosting/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.local.hosting/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
}
}
However, running the docker-compose starts two containers, 1 app and 2 nginx, but nginx exits with some error. May I ask, what could be the potential cause of the service failure. Look forward to all the suggestions, thanks in advance!
Update:
Adding the output from terminal upon executing the docker-compose file:
user#user:~/Desktop/App$sudo docker-compose up
Starting production-local-app ... done
Starting production_nginx ... done
Attaching to production_nginx, production-local-app
production_nginx | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
production_nginx | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
production_nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
production_nginx | 10-listen-on-ipv6-by-default.sh: info: IPv6 listen already enabled
production_nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
production_nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
production_nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
production_nginx | 2021/12/05 16:27:03 [emerg] 1#1: open() "/etc/letsencrypt/options-ssl-nginx.conf" failed (2: No such file or directory) in /etc/nginx/nginx.conf:23
production_nginx | nginx: [emerg] open() "/etc/letsencrypt/options-ssl-nginx.conf" failed (2: No such file or directory) in /etc/nginx/nginx.conf:23
production_nginx exited with code 1
production-local-app |
production-local-app | Web Server starting at http://localhost:8080 - press Ctrl/Cmd+C to stop the server.

Related

Nginx connection refused

I'm using docker containers to host a web app. I have three main containers: MySQL, flask and Nginx. The first two work as expected and the latter seems to be working fine as no error is displayed in the docker-compose startup.
Nginx container initialization output:
nginx | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
nginx | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
nginx | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf is not a file or does not exist
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
nginx | 2022/04/07 13:09:13 [notice] 1#1: using the "epoll" event method
nginx | 2022/04/07 13:09:13 [notice] 1#1: nginx/1.21.6
nginx | 2022/04/07 13:09:13 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
nginx | 2022/04/07 13:09:13 [notice] 1#1: OS: Linux 4.19.130-boot2docker
nginx | 2022/04/07 13:09:13 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
nginx | 2022/04/07 13:09:13 [notice] 1#1: start worker processes
nginx | 2022/04/07 13:09:13 [notice] 1#1: start worker process 21
Nginx dockerfile
# Dockerfile-nginx
FROM nginx:latest
# Nginx will listen on this port
# EXPOSE 80
# Remove the default config file that
# /etc/nginx/nginx.conf includes
RUN rm /etc/nginx/conf.d/default.conf
# We copy the requirements file in order to install
# Python dependencies
COPY nginx.conf /etc/nginx/conf.d/
Containers after being deployed and their respective ports:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bffffcfe2f70 sc_server_nginx "/docker-entrypoint.…" 14 seconds ago Up 13 seconds 0.0.0.0:80->80/tcp nginx
a73d958c1407 sc_server_flask "uwsgi app.ini" 9 hours ago Up 9 hours 8080/tcp flask
d273db5f80ef mysql:5.7 "docker-entrypoint.s…" 21 hours ago Up 9 hours (healthy) 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
I'm new to Nginx server, so I guess it may be a newbie error. I'm trying to redirect all the traffic from my host machine's 80 port to docker's 80 which redirects the traffic to the WSGI container via a socket.
I'm using the following Nginx configuration (nothing close to fancy I guess):
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass flask:8080;
}
}
As you can see the server listens at port 80 and redirects all the traffic via the socket uwsgi_pass flask:8080; to the WSGI container that is hosting the app.
However, whenever I type 127.0.0.1:80 or 0.0.0.0:80 in my browser the connection is refused. I have no firewall deployed, so I guess that there is no problem with port 80 being down.
This is my app.ini configuation file, in which the initialization and deployment params are indicated:
[uwsgi]
wsgi-file = wsgi.py
; This is the name of the variable
; in our script that will be called
callable = app
; We use the port 8080 which we will
; then expose on our Dockerfile
socket = :8080
; Set uWSGI to start up 4 workers
processes = 4
threads = 2
master = true
chmod-socket = 660
vacuum = true
die-on-term = true
Additionally, I also include the docker-compose.yml (I guess it may be helpful):
docker-compose.yml
services:
flask:
build: ./flask
container_name: flask
restart: always
environment:
- APP_NAME=MyFlaskApp
- YOURAPPLICATION_SETTINGS=docker_config.py
expose:
- 8080
depends_on:
mysql:
condition: service_healthy
mysql:
image: mysql:5.7
container_name: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD:
MYSQL_DATABASE:
MYSQL_USER:
MYSQL_PASSWORD:
volumes:
- ./db/init.sql:/data/application/init.sql
healthcheck:
test: mysql -u -p --database -e "show tables;"
interval: 3s
retries: 5
start_period: 30s
nginx:
build: ./nginx
container_name: nginx
restart: always
depends_on:
- mysql
- flask
ports:
- "80:80"
Anyone can help?
Update
I've used Wireshark to scan the loopback interface to see the server's response to 0.0.0.0:80 (I suspect there might be some problem with port 80) and I get the following payload:
Update 2:
After deploying the app in EC2 everything seems to be working fine. Thus, it has to be some problem with port 80 at localhost. My machine's OS is macOS Monterrey 12.4 and the system firewall is turned down.

"Welcome to Nginx!" - Docker-Compose, using uWSGI, Flask, nginx

My Problem:
I am using Ubuntu 18.04 and a docker-compose based solution with two Docker images, one to handle Python/uWSGI and one for my NGINX reverse proxy. No matter what I change, it always seems like WSGI is unable to detect my default application. Whenever I run docker-compose up, and navigate to localhost:5000 I get the above default splash.
The complete program appears to work on our CentOS 7 machines. However, when I try to execute it on my Ubuntu test machine, I can only get the "Welcome to NGINX!" page.
Directory Structure:
/app
- app.conf
- app.ini
- app.py
- docker-compose.py
- Dockerfile-flask
- Dockerfile-nginx
- requirements.txt
/templates
(All code snippets have been simplified to help isolate the problem)
Here is an example of my docker traceback:
clocker_flask_1
[uWSGI] getting INI configuration from app.ini
current working directory: /app
detected binary path: /usr/local/bin/uwsgi
uwsgi socket 0 bound to TCP address 0.0.0.0:5000 fd 3
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
*** Operational MODE: preforking+threaded ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x558072010e70 pid: 1 (default app)
clocker_nginx_1
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
Here is my docker-compose.yaml:
# docker-compose.yml
version: '3'
services:
flask:
image: webapp-flask
build:
context: .
dockerfile: Dockerfile-flask
volumes:
- "./:/app:z"
- "/etc/localtime:/etc/localtime:ro"
environment:
- "EXTERNAL_IP=${EXTERNAL_IP}"
nginx:
image: webapp-nginx
build:
context: .
dockerfile: Dockerfile-nginx
ports:
- 5000:80
depends_on:
- flask
Dockerfile-flask:
FROM python:3
ENV APP /app
RUN mkdir $APP
WORKDIR $APP
EXPOSE 5000
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD [ "uwsgi", "--ini", "app.ini" ]
Dockerfile-nginx
FROM nginx:latest
EXPOSE 80
COPY app.conf /etc/nginx/conf.d
app.conf
server {
listen 80;
root /usr/share/nginx/html;
location / { try_files $uri #app; }
location #app {
include uwsgi_params;
uwsgi_pass flask:5000;
}
}
app.py
# Home bit
#application.route('/')
#application.route('/home', methods=["GET", "POST"])
def home():
return render_template(
'index.html',
er = er
)
if __name__ == "__main__":
application.run(host='0.0.0.0')
app.ini
[uwsgi]
protocol = uwsgi
module = app
callable = application
master = true
processes = 2
threads = 2
socket = 0.0.0.0:5000
vacuum = true
die-on-term = true
max-requests = 1000
The nginx image comes with a main configuration file, /etc/nginx/nginx.conf, which loads every conf file in the conf.d folder -- including your nemesis in this case, a stock /etc/nginx/conf.d/default.conf. It reads as follows (trimmed a bit for concision):
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
So, your app.conf and this configuration are both active. The reason why this default one wins, though, is because of the server_name directive that it has (and yours lacks) -- when you're hitting localhost:5000, nginx matches based on the hostname and sends your request there.
To fix this easily, you can just remove that file in your Dockerfile-nginx:
RUN rm /etc/nginx/conf.d/default.conf

Error trying to run nginx using docker-compose with custom conf.d

I'm trying to set up a web server with multiple containers - but starting with a simple setup for my reverse proxy.
My docker-compose.yml looks as follows:
version: '3'
services:
reverse-proxy:
container_name: reverse-proxy
hostname: reverse-proxy
image: nginx:latest
ports:
- 80:80
volumes:
- ./nginx-config/conf.d:/etc/nginx/conf.d
- ./html:/usr/share/nginx/html
environment:
- NGINX_PORT=80
- ENV=development
Having nginx-config folder structure like:
nginx-config
|- templates
|-default.conf.template
|- sites-available
|- mysite.conf.template
And default.conf.template that looks like:
server {
listen ${NGINX_PORT} default_server;
listen [::]:${NGINX_PORT} default_server;
server_name _;
root /usr/share/nginx/html;
charset UTF-8;
error_page 404 /notfound.html;
location = /notfound.html {
allow all;
}
location / {
return 404;
}
access_log off;
log_not_found off;
error_log /var/log/nginx/error.log error;
}
However, whenever I run docker-compose --context myremote up it doesn´t work, throwing the following output:
reverse-proxy | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
reverse-proxy | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
reverse-proxy | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
reverse-proxy | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
reverse-proxy | 10-listen-on-ipv6-by-default.sh: /etc/nginx/conf.d/default.conf differs from the packaged version, exiting
reverse-proxy | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
reverse-proxy | /docker-entrypoint.sh: Configuration complete; ready for start up
It all generates the right output under nginx-config/conf.d/default.conf at least on my local machine.
Is there any way I can take advantage of custom config and templates using docker-compose without running into such an issue?
Problem solved.
I was trying to perform this using a docker context onto an EC2 machine.
Whilst Docker --context [context] has been part of the stable version (at least for MacOS) for a while, docker-compose --context [context] was added on v1.26.0-rc2 so at this moment in time you need Docker Edge installed in order to make it work.
I was using set context [context] rather than the explicit --context form which meant I was actually deploying locally but being unaware of it.

Docker: nginx reverse proxy and how to configure multiple services (i.e on 8080 &8081)

I am a bit stuck with configuring multiple services where nginx is the proxy server.
running :
docker -v
Docker version 19.03.8, build afacb8b7f0
docker-compose -v
docker-compose version 1.23.2, build 1110ad01
I want to start with this test, everything in the same docker-compose.yml-file :
link to jwilder/nginx
proxy : nginx-server (jwilder/nginx-proxy:0.7.0 , which is nginx 1.17.6)
container1 : httpd:2.4
container2 : httpd:2.4
updating my /etc/hosts before I start
127.0.0.1 container1.com
127.0.0.1 container2.com
Here is my docker-compose.yml-file (obs -> version 3.7)
version: '3.7'
services:
proxy:
image: jwilder/nginx-proxy:0.7.0
container_name: proxy-test
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx-proxy.conf:/etc/nginx/conf.d/nginx-proxy.conf:ro
container1:
image: httpd:2.4
container_name: container-1
environment:
- VIRTUAL_HOST:container1.com
ports:
- 8080:80
container2:
image: httpd:2.4
container_name: container-2
environment:
- VIRTUAL_HOST:container2.com
ports:
- 8081:80
here is my nginx-proxy.conf:
server {
listen 80;
server_name container1.com;
location / {
proxy_pass http://localhost:8080;
}
}
server {
listen 80;
server_name container2.com;
location / {
proxy_pass http://localhost:8081;
}
}
After this I run the
docker exec container-1 sed -i 's/It works!/Container 1/' /usr/local/apache2/htdocs/index.html AND docker exec container-2 sed -i 's/It works!/Container 2/' /usr/local/apache2/htdocs/index.html
Test 1 : with curl to the port 8080 and port 8081
curl localhost:8080
response -> Container 1
curl localhost:8081
response -> Container 2
Test 2 : with curl to container1.com AND container2.com
curl container1.com
status 502
curl container2.com
status 502
Are the settings in my conf wrong ?
Troubleshooting 1:
docker exec -it proxy-test bash
I can see that the nginx-proxy.conf is in the directory (/etc/nginx/conf.d)
/etc/nginx/conf.d/default.conf is there as well
Troubleshooting 2: The proxy-log (Connection refused - while connecting to upstream)
proxy-test | nginx.1 | 2020/04/03 10:52:08 [error] 61#61: *9 connect() failed (111: Connection refused) while connecting to upstream, client: 172.29.0.1, server: container1.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "container1.com"
proxy-test | nginx.1 | 2020/04/03 10:52:08 [error] 61#61: *9 connect() failed (111: Connection refused) while connecting to upstream, client: 172.29.0.1, server: container1.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "container1.com"
Found 2 solutions to this.
(1)
the first is to update the nginx-proxy.conf with the name of the containers instead of pointing to http://localhost:8080; and http://localhost:8081; :
new config-file
server {
listen 80;
server_name container1.com;
location / {
proxy_pass http://container-1;
}
}
server {
listen 80;
server_name container2.com;
location / {
proxy_pass http://container-2;
}
}
(2)
Leaving out the nginx-proxy.conf-file , docker-compose.yml will map things correctly.

Suppervisor - php-fpm leads to 502 Bad Gateway

I have a web application based on php and nginx images ... Everything works great until I set a command under the PHP configuration:
command: /usr/bin/supervisord -c /symfony/supervisord.conf
docker-compose.yml
version: '2'
services:
php:
build: docker/php
tty: true
volumes:
- '.:/symfony'
command: /usr/bin/supervisord -c /symfony/supervisord.conf
nginx:
image: nginx:1.11
tty: true
volumes:
- './public/:/symfony'
- './docker/nginx/default.conf:/etc/nginx/conf.d/default.conf'
ports:
- '80:80'
links:
- php
This is my default.conf
server {
server_name ~.*;
location / {
root /symfony;
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
client_max_body_size 50m;
fastcgi_pass php:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /symfony/public/index.php;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}
This is my supervisord.conf
[unix_http_server]
file=/tmp/supervisor.sock
[supervisord]
logfile=/tmp/supervisord.log
pidfile=/var/run/supervisord.pid
nodaemon=true
Nginx logs show me:
nginx_1 | 2018/10/02 00:42:36 [error] 11#11: 1 connect() failed
(111: Connection refused) while connecting to upstream, client:
172.23.0.1, server: ~., request: "GET / HTTP/1.1", upstream: "fastcgi://172.23.0.2:9000", host: "127.0.0.1"
As we see, nginx report a 502 Bad Gateway error. If i remove the last line, CMD, everything works fine. If I remove the line and I acess via docker-compose exec php bash and launch the command manually everything work also.
Any Idea why adding that command leads to 502 Bad Gateway ??
Ok I found a solution It was a problem with supervisor. Because each time we launch our service supervisor, the php-fpm service is stopped automatically that's why it should add a configuration that will relaunch the php-fpm but this time from supervisor configuration.
[program:php-fpm]
command = /usr/local/sbin/php-fpm
autostart=true
autorestart=true
For anyone else with similar problem:
Don't forget that command key in docker-compose.yml file overrides default CMD in Dockerfile, therefore that command won't be run.
For example, if php:7.4-fpm final command is CMD php-fpm, it won't be run.
Therefore if you have some custom logic for running after container is ran, don't forget to include it in your command, e.g.:
command: bash -c "php-fpm & npm run dev"

Resources