Docker-compose and nginx proxy - docker

I am trying to use jwilder/nginx-proxy as a reverse proxy for my angular2 app that is broken down into 3 containers (angular, express and database).
I have tried different configurations to proxy requests to my app on port 80, however when I try to run docker-compose I get :
ERROR: for angular Cannot start service angular: driver failed programming
external connectivity on endpoint example_angular_1
(335ce6d0c775b7837eb436fff97bbb56bfdcaece22d51049e1eb4bf5ce45553c): Bind for
0.0.0.0:80 failed: port is already allocated
While the message is pretty clear that there is a conflict on port 80, I cannot figure out a way to go around it, it works just fine when I set my angular container to work on port 4200 but then I have to specify the port number in url every time I want to visit the page. I am using the reverse proxy because it is not the only app that will be running in my environment
Below is my docker-compose.yml
version: '3'
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports: - "80:80"
volumes: - /var/run/docker.sock:/tmp/docker.sock:ro
angular:
build: client
ports: - "80"
environment:
- VIRTUAL_HOST=example.com
- VIRTUAL_PORT=80
restart: always
express:
build: server
ports: - "3000:3000"
links: - database
restart: always
database:
image: mongo
ports: - "27017:27017"
restart: always
networks:
default:
external:
name: nginx-proxy
And Dockerfile for the angular container
FROM node:8-alpine as builder
COPY package.json package-lock.json ./
RUN npm set progress=false && npm config set depth 0 && npm cache clean --force
RUN npm i && mkdir /ng-app && cp -R ./node_modules ./ng-app
WORKDIR /ng-app
COPY . .
RUN $(npm bin)/ng build --prod --build-optimizer
FROM nginx:1.13.3-alpine
COPY nginx/default.conf /etc/nginx/conf.d/
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /ng-app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
EXPOSE 80

The problems is that you're trying to open the port 80 on the host twice. Once for the nginx-proxy and once for angular. Remove the "ports 80" from angular.

The browser will speak to the container on the virtual_port that you set.
Maybe you can direct the the request to the backend through an api endpoint

If you want to use nginx as a reverse proxy, you need to access to it using the 80 port. Then modify the nginx config to redirect to your angular container and port (81 for example). Try this: "proxy_pass http://angular:81". This should work.

Related

Can't access web container from outside (Windows Docker-Desktop)

i'm using Docker-Desktop on Windows and i'm trying to get running 3 containers inside docker-desktop.
After few research and test, i get the 3 container running [WEB - API - DB], everything seems to compile/run without issue in the logs but i'can't access my web container from outside.
Here's my dockerfile and docker-compose, what did i miss or get wrong ?
[WEB] dockerfile
FROM node:16.17.0-bullseye-slim
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
CMD ["npm", "run", "start"]
[API] dockerfile
FROM openjdk:17.0.1-jdk-slim
WORKDIR /app
COPY ./target/test-0.0.1-SNAPSHOT.jar /app
#EXPOSE 2022 (the issue is the same with or without this line)
CMD ["java", "-jar", "test-0.0.1-SNAPSHOT.jar"]
Docker-compose file
version: "3.8"
services:
### FRONTEND ###
web:
container_name: wallet-web
restart: always
build: ./frontend
ports:
- "80:4200"
depends_on:
- "api"
networks:
customnetwork:
ipv4_address: 172.20.0.12
#networks:
# - "api"
# - "web"
### BACKEND ###
api:
container_name: wallet-api
restart: always
build: ./backend
ports:
- "2022:2022"
depends_on:
- "db"
networks:
customnetwork:
ipv4_address: 172.20.0.11
#networks:
# - "api"
# - "web"
### DATABASE ###
db:
container_name: wallet-db
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
customnetwork:
ipv4_address: 172.20.0.10
#networks:
# - "api"
# - "web"
networks:
customnetwork:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
# api:
# web:
Listening on:
enter image description here
I found several issue similar to mine but the solution didn't worked for me.
If i understand you are trying to access on port 80. To do that, you have to map your container port 4200 to 80 in yaml file 80:4200 instead of 4200:4200.
https://docs.docker.com/config/containers/container-networking/
Have you looked in the browsers development console, if there comes any error. Your docker-compose seems not to have any issue.
How ever lets try to debug it:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6245eaffd67e nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:4200->80/tcp test-api-1
copy the container id then execute:
docker exec -it 6245eaffd67e bin/bash
Now you are inside the container. Instead of the id you can use also the containers name.
curl http://localhost:80
Note: in my case here i just create a container from an nginx image.
In your case use the port where your app is running. Control it in your code if you arent sure. A lot of Javascript-frameworks start default on 3000.
If you get an error: curl command not found, install it in your image:
FROM node:16.17.0-bullseye-slim
USER root # to install dependencies you need sudo permissions su we tell the image that it is root
RUN apt update -y && apt install curl -y
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
USER node # we dont want to execute the image as root so we put user node (this user is defined in the node:16.17.0-bullseye-slim image)
CMD ["npm", "run", "start"]
Now the curl should work (if it doesnt already).
The same should work from your host.
Here is an important thing:
The localhost, always refers to the fisical computer, or the container itselfs where you are refering. Every container and your PC have localhost and they are not the same.
In the docker-compose you just map the port host/container, so your PC (host) where docker is running can access the docker network from the host on the host port you defined, inside the port of the container.
If you cant still access from your host, try to change the host ports 2022, 4200 ecc. Could be possible that something conflicts on your Windows machine.
It happens sometimes that the docker networks can create some conflicts.
Execute a docker-compose down, so it should be delete and recreated.
Still not working?
Reset docker-desktop to factory settings, control if you have last version (this is always better).
If all this doesnt help, let me know so we can debugg further.
For the sake of clarity i post you here the docker-compose which i used to check. I just used nginx to test the ports as i dont have your images.
version: "3.8"
services:
### FRONTEND ###
web:
restart: always
image: nginx
ports:
- "4200:80"
depends_on:
- "api"
networks:
- "web"
### BACKEND ###
api:
restart: always
image: nginx
ports:
- "2022:80"
depends_on:
- "db"
networks:
- "api"
- "web"
### DATABASE ###
db:
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
- "api"
networks:
api:
web:
```
Update:
You can log what happens in the conatiner like so:
```
docker logs containerid/name
```
If you are using Visualcode there is excellent extension for docker build also by Microsoft:
Just search docker in the extensions. Has something like 20.000.000 downloads and can help you a lot debugging containers ecc. After installing it you see the dockericon on the left toolbar.
If you can see directly the errors that occurs in the logs, maybe you can post them partially. So it would be possible to understand. Please tell also something about your Frontendapp architecture, (react-app, angular). There are some frameworks that need to be startet on 0.0.0.0 instead of 127.0.0.1 or they dont work.

I'm getting `ERR_EMPTY_RESPONSE` in Docker Compose even though the two individual containers work when run separately

So I have a basic frontend and backend. The backend relies on some environment variables and this is my docker-compose.yml.
version: "3.9"
services:
backend:
env_file:
- .env
build:
context: ./backend
container_name: fastapi-api
ports:
- 80:80
frontend:
build:
context: ./frontend
container_name: vue-ui
ports:
- 8080:8080
links:
- backend
This gives me ERR_EMPTY_RESPONSE when I go to http://127.0.0.1:8080/, however when I ran the individual Dockerfiles for my frontend and backend, this goes smoothly
My frontend
FROM node:lts-alpine
# install simple http server for serving static content
RUN npm install -g http-server
# make the 'frontend' folder the current working directory
WORKDIR /frontend
# copy both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
# install project dependencies
RUN npm install
# copy project files and folders to the current working directory (i.e. 'app' folder)
COPY . .
# build app for production with minification
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]
My backend
FROM tiangolo/uvicorn-gunicorn:python3.8
LABEL maintainer="Sebastian Ramirez <tiangolo#gmail.com>"
WORKDIR /backend
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
EXPOSE 80
This is what I see from running docker ps
This is what's happening, frontend requests are being sent to the wrong place
I want it to go here
So requests should go to port 80 not port 8000
This is what I see from dev tools
However this is my code
axios
.post(`http://127.0.0.1:80/city/`, {
city_name: this.current_city
})
Where are the extra 0s coming from?
This is what happens when I ran the two containers separately
By looking at the docker ps output I would guess that you have by accident switched ports for backend and frontend in configuration. Frontend has unmapped port 80 and backend has unmapped port 8080.
Try this one:
version: "3.9"
services:
backend:
env_file:
- .env
build:
context: ./backend
container_name: fastapi-api
ports:
- 8080:8080
frontend:
build:
context: ./frontend
container_name: vue-ui
ports:
- 80:80
links:
- backend

Docker Compose with NGINX proxy pass thru not working

Following is my Docker Compose file & NGINX conf file.
The application seems to work and NGINX is also up, but the proxy_pass setting doesn't seem to work properly.
File
docker-compose.yaml
networks:
webapp:
services:
web:
image: nginx
volumes:
- ./data/ntemplates:/etc/nginx/templates
- ./webapp.conf:/etc/nginx/conf.d/webapp.conf
ports:
- "8080:80"
networks:
- webapp
pyweb:
build: .
ports:
- "5000:5000"
networks:
- webapp
redis:
image: "redis:alpine"
networks:
- webapp
File webapp.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
proxy_pass "http://pyweb_1:5000/";
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}
Service pyweb is working if properly if directly accessed by http://pyweb_1:5000
I created this app based on docker getting started page
For completeness below are other files and seems to be working just fine.
File Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
File requirement.txt
flask
redis
File app.py
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
#app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
EDIT:
You're currently not using the nginx configuration. I didn't read carefully your docker-compose file. You can fix it by mapping the webapp.conf on /etc/nginx/conf.d/default.conf. e.g.
services:
web:
image: nginx
volumes:
- ./data/ntemplates:/etc/nginx/templates
- ./webapp.conf:/etc/nginx/conf.d/default.conf
ports:
- "8080:80"
depends_on:
- pyweb
networks:
- webapp
There are 2 issues:
you don't know what container name will be used by docker-compose
you don't know the order used to start the containers
docker-compose allows you to solve the first issue in 2 ways:
define a container_name subsection
use the service name
This means that you can simply use proxy_pass "http://pyweb:5000/"; in your nginx setup
The second issue can be fixed by adding a depends_on subsection in the nginx service. e.g.
services:
web:
image: nginx
volumes:
- ./data/ntemplates:/etc/nginx/templates
- ./webapp.conf:/etc/nginx/conf.d/webapp.conf
depends_on:
- pyweb
ports:
- "8080:80"
networks:
- webapp
Nevertheless, the depends_on might not be enough since it does not check the service status but it only make sure that the docker service is started (as stated in the documentation).
You'll need to find another way to monitor if the service is actually started.

How to deploy docker react app on clever-cloud

I am new to both clever cloud and docker. I want to create an application running on docker with nginx and react to clever cloud. But, everytime I push to clever cloud, deployment failed
ERROR MESSAGE:
Nothing listening on 0.0.0.0:8080 yet. If the deployment fails after this message, please update your configuration and redeploy.
My docker-compose file:
version: '3.7'
services:
front:
container_name: front
build:
context: .
dockerfile: Dockerfile
volumes:
- '.:/app'
- '/app/node_modules'
ports:
- 8080:80
labels:
NAME: "App Front"
networks:
- app-network
environment:
- CHOKIDAR_USEPOLLING=true
expose:
- 8080
networks:
app-network:
driver: bridge
Content of the Dockerfile
FROM node:alpine as builder
WORKDIR /app
COPY . ./
RUN yarn install
RUN yarn run build
FROM nginx:alpine
COPY docker/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
create-react-app works fine on Clever Cloud.
Your app should listen on 0.0.0.0:8080, you can set this with environment variables (HOST and PORT).
If you are deploying a Docker application that is not listening on 8080, you can use the CC_DOCKER_EXPOSED_HTTP_PORT environment variable to define the correct port.
NOTE: There are some issues with the latest version (3.4.1)
https://github.com/facebook/create-react-app/issues/8688
Several solutions are proposed to fix this :
Add stdin_open: true on your docker-compose command
Add an CI=true as an environment variable
Downgrade your react-scripts to 3.4.0

how to access node api which is running as docker container

I have built a docker-compose file for my node js application that has been dockerized, But I don't know how to make the API call to that node js app which is running as a docker container, Please help me with this concern.
My DockerFile:
FROM node:10.15-slim
ENV NODE_ENV=production
WORKDIR /app
COPY package.json package-lock*.json ./
RUN npm install && npm cache clean --force
COPY . .
CMD ["node", "./bin/www"]
My Docker-compose file:
version: '2.4'
services:
express:
build:
context: .
dockerfile: Dockerfile
command: /app/node_modules/.bin/nodemon ./bin/www
ports:
- 3000:3000
volumes:
- .:/app
environment:
- DEBUG=sample-express:*
- NODE_ENV=development
You'll need to expose the port from docker on which your application is running.
Let's say your application is running on port 8080 inside docker, here's how you can expose that specific port:
EXPOSE 8080
Then you'll need to map the port exposed by docker tthato your local port. Here's how you can do it in docker:
docker run -p 49160:8080 -d docker_image
And if you're working with docker-compose, you'll do it like this:
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
ports:
- "8080:8080"
UPDATE
Let's say you want to send /api requests to back-end server. This is how you'll do it in nginx conf:
server {
listen 80
location /api {
proxy_pass http://backend:8080/;
}
}
I hope it helps.

Resources