I'm trying to dockerize my microservices and i'm so newbie on traefik.
I have multiple micro services which connect each other in projects. I made a common project to handle common containers.
# docker/docker-compose.yml
version: '3'
services:
mysql:
container_name: common-mysql
build:
context: ./mysql
restart: on-failure
networks:
- web
environment:
- MYSQL_USER=${DATABASE_USER}
- MYSQL_PASSWORD=${DATABASE_PASSWORD}
- MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD}
ports:
- "3306:3306"
mongo:
container_name: common-mongo
build:
context: ./mongo
restart: on-failure
networks:
- web
ports:
- "27017:27017"
memcached:
container_name: common-memcached
build:
context: ./memcached
restart: on-failure
rabbitmq:
container_name: common-rabbitmq
build:
context: ./rabbitmq
restart: on-failure
networks:
- web
ports:
- "5672:5672"
- "15672:15672"
environment:
- RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS}
elasticsearch:
container_name: common-elasticsearch
build:
context: ./elasticsearch
restart: on-failure
networks:
- web
ports:
- "9200:9200"
- "9300:9300"
environment:
- http.host=0.0.0.0
- transport.host=localhost
- network.host=0.0.0.0
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
traefik:
container_name: "traefik"
build:
context: ./traefik
restart: on-failure
networks:
- web
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./traefik/config/static.yml:/etc/traefik/traefik.yml"
- "./traefik/config/dynamic.yml:/etc/traefik/dynamic.yml"
- "./traefik/certs:/etc/certs"
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.web.local`)"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.api.service=api#internal"
blackfire:
container_name: common-blackfire
image: blackfire/blackfire
networks:
- web
restart: always
ports: [ "8707" ]
environment:
BLACKFIRE_SERVER_ID: ${BLACKFIRE_SERVER_ID}
BLACKFIRE_SERVER_TOKEN: ${BLACKFIRE_SERVER_TOKEN}
networks:
web:
external: true
Then, i created docker composes and nginx confs for the microservices.
For project 1:
version: "3.1"
services:
app1-nginx:
container_name: app1-nginx
build: docker/nginx
working_dir: /application
restart: on-failure
networks:
- web
volumes:
- ./var/nginx_logs:/var/log/nginx
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- "./docker/certs:/etc/certs"
labels:
- "traefik.enable=true"
- "traefik.http.routers.app1-nginx.rule=Host(`app1.web.local`)"
- "traefik.http.routers.app1-nginx.tls=true"
depends_on:
- app1-fpm
app1-fpm:
container_name: app1-fpm
build: docker/php-fpm
working_dir: /application
restart: on-failure
networks:
- web
volumes:
- .:/application:cached
- ./var/log:/application/var/log
- ./docker/php-fpm/php-ini-overrides.ini:/usr/local/etc/php/conf.d/php-overrides.ini
- ./docker/php-fpm/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
- ~/.ssh/:/root/.ssh/
labels:
- traefik.enable=false
environment:
BLACKFIRE_CLIENT_ID: ${BLACKFIRE_CLIENT_ID}
BLACKFIRE_CLIENT_TOKEN: ${BLACKFIRE_CLIENT_TOKEN}
networks:
web:
external: true
server {
server_name app1.web.local;
listen 80;
listen 443 ssl;
ssl_certificate /etc/certs/local-cert.pem;
ssl_certificate_key /etc/certs/local-key.pem;
root /application/public;
index index.php;
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
location ~ \.php$ {
fastcgi_pass app1-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
For project 2:
version: "3.1"
services:
app2-nginx:
container_name: app2-nginx
build: docker/nginx
working_dir: /application
restart: on-failure
networks:
- web
volumes:
- ./var/nginx_logs:/var/log/nginx
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- "./docker/certs:/etc/certs"
labels:
- "traefik.enable=true"
- "traefik.http.routers.app2-nginx.rule=Host(`app2.web.local`)"
- "traefik.http.routers.app2-nginx.tls=true"
depends_on:
- app2-fpm
app2-fpm:
container_name: app2-fpm
build: docker/php-fpm
working_dir: /application
restart: on-failure
networks:
- web
volumes:
- .:/application:cached
- ./var/log:/application/var/log
- ./docker/php-fpm/php-ini-overrides.ini:/usr/local/etc/php/conf.d/php-overrides.ini
- ./docker/php-fpm/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
- ~/.ssh/:/root/.ssh/
labels:
- traefik.enable=false
environment:
BLACKFIRE_CLIENT_ID: ${BLACKFIRE_CLIENT_ID}
BLACKFIRE_CLIENT_TOKEN: ${BLACKFIRE_CLIENT_TOKEN}
networks:
web:
external: true
server {
server_name app2.web.local;
listen 80;
listen 443 ssl;
ssl_certificate /etc/certs/local-cert.pem;
ssl_certificate_key /etc/certs/local-key.pem;
root /application/public;
index index.php;
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
location ~ \.php$ {
fastcgi_pass app2-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
When i docker compose up for both of them, services work great.
But my second project requires the first one and send a request from project.
I send the request from second to the one as 'https://app1.web.local' it fails and throws 443 connection refused.
If i change the url as ip it works or if i add the host name with ip inside container it works too.
But the ip changes every time while container ups.
How can i solve this? Thanks.
Related
I'm trying to get phpmyadmin to work on my live server in Vultr. I have a full-stack react app for the front-end and express Node Js for the back-end as well as mysql for database and phpmyadmin to create tables and stuff. Both React app and Express Node js work, but phpmyadmin doesn't work.
Below is my docker-compose file:
version: '3.7'
services:
mysql_db:
image: mysql
container_name: mysql_container
restart: always
cap_add:
- SYS_NICE
volumes:
- ./data:/var/lib/mysql
ports:
- "3306:3306"
env_file:
- .env
environment:
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
MYSQL_HOST: "${MYSQL_HOST}"
MYSQL_DATABASE: "${MYSQL_DATABASE}"
MYSQL_USER: "${MYSQL_USER}"
MYSQL_PASSWORD: "${MYSQL_PASSWORD}"
networks:
- react_network
phpmyadmin:
depends_on:
- mysql_db
image: phpmyadmin/phpmyadmin:latest
container_name: phpmyadmin_container
restart: always
ports:
- "8080:80"
env_file:
- .env
environment:
- PMA_HOST=mysql_db
- PMA_PORT=3306
- PMA_ABSOLUTE_URI=https://my-site.com/admin
- PMA_ARBITRARY=1
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
networks:
- react_network
api:
restart: always
image: mycustomimage
ports:
- "3001:80"
container_name: server_container
env_file:
- .env
depends_on:
- mysql_db
environment:
MYSQL_HOST_IP: mysql_db
networks:
- react_network
client:
image: mycustomimage
ports:
- "3000:80"
restart: always
stdin_open: true
environment:
- CHOKIDAR_USEPOLLING=true
container_name: client_container
networks:
- react_network
nginx:
depends_on:
- api
- client
build: ./nginx
container_name: nginx_container
restart: always
ports:
- "443:443"
- "80"
volumes:
- ./nginx/conf/certificate.crt:/etc/ssl/certificate.crt:ro
- ./nginx/certs/private.key:/etc/ssl/private.key:ro
- ./nginx/html:/usr/share/nginx/html
networks:
- react_network
volumes:
data:
conf:
certs:
webconf:
html:
networks:
react_network:
Below is my nginx configuration file:
upstream client {
server client:3000;
}
upstream api {
server api:3001;
}
server {
listen 443 ssl http2;
server_name my-site.com;
ssl_certificate /etc/ssl/certificate.crt;
ssl_certificate_key /etc/ssl/private.key;
location / {
proxy_pass http://client;
}
location /admin {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://phpmyadmin:8080;
}
location /sockjs-node {
proxy_pass http://client;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass http://api;
}
}
server {
listen 80;
server_name my-site.com www.my-site.com;
return 301 https://my-site.com$request_uri;
}
I honestly don't know what I'm missing here! If anyone can help me please!!
I get a 502 Bad Gateway error!
I've installed my application via docker on nginx. (Laravel project) but it returns "file not found" when try to change nginx root to var/www/public from var/www.
I'm sharing my codes below:
my app.conf:
server {
listen 80;
index index.php index.html;
root /var/www/public;
location / {
try_files $uri /index.php?$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
server_tokens off;
}
my docker-compose.yml
version: '3.7'
services:
app:
build:
context: docker/php
dockerfile: Dockerfile
container_name: app
image: jjuanrivvera99/laravel:mysql-alpine
restart: always
depends_on:
- redis
volumes:
- ./:/var/www
- ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network
web:
image: nginx:alpine
restart: always
depends_on:
- app
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www
- ./docker/nginx/:/etc/nginx/conf.d/
networks:
- app-network
queue:
restart: always
depends_on:
- redis
image: jjuanrivvera99/laravel:mysql-alpine
environment:
CONTAINER_ROLE: "queue"
volumes:
- "./:/var/www/"
networks:
- app-network
scheduler:
restart: always
depends_on:
- redis
image: jjuanrivvera99/laravel:mysql-alpine
environment:
CONTAINER_ROLE: "scheduler"
volumes:
- "./:/var/www/"
networks:
- app-network
node:
image: jjuanrivvera99/node:alpine
restart: always
build:
context: docker/node
dockerfile: Dockerfile
container_name: node
volumes:
- ./:/var/www
mysql:
image: mysql:5.7.22
restart: always
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: mdpocr
MYSQL_ROOT_PASSWORD: Bugbytes13**
volumes:
- mysql-data:/var/lib/mysql/
- ./docker/mysql/my.cnf:/etc/mysql/my.cnf
networks:
- app-network
redis:
image: redis
restart: always
ports:
- 6379:6379
volumes:
- redis-data:/data
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
driver: local
redis-data:
driver: local
whats wrong with it?
It works well when I change root to /var/www. But it returns "file not found" when I change it to /var/www/public.
What I am trying to achieve
I am trying to integrate an SSL certificate for my production site, bonus if I could create a self-signed certificate for local development.
The issue I am having
When trying to integrate the nginx-proxy and letsencrypt-companion it always results in a redirect loop or 502 Bad gateway error.
I've looked around at a variety of ways to integrate these 2 companions but I still am stuck about how to integrate this but always ask myself the same questions when attempting to integrate into my environment.
More detail about my environment
I am running a multi-container Docker Compose web app which uses PHP/PHP-FPM 7.2, MySQL & Nginx. The config looks like:
version: '3.1'
networks:
mywebapp:
services:
nr_nginx:
build: ./env/nginx
networks:
- mywebapp
ports:
- 80:80
- 443:443
env_file:
- ./env/nginx/.env
depends_on:
- nr_php72
tty: true
volumes:
- ./src:/home/www/mywebapp/src
- ./storage:/home/www/storage/mywebapp
- ./data/nginx/logs:/var/log/nginx
- ./env/nginx/webserver/nginx.conf:/etc/nginx/nginx.conf
- ./env/nginx/webserver/conf.d:/etc/nginx/conf.d
- ./env/nginx/webserver/defaults:/etc/nginx/defaults
- ./env/nginx/webserver/global:/etc/nginx/global
- ./env/nginx/ssl/:/etc/letsencrypt/
- ./env/nginx/share:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
nr_mysql:
build: ./env/mysql
networks:
- mywebapp
ports:
- 3306:3306
env_file:
- ./env/mysql/.env
volumes:
- ./data/mysql:/var/lib/mysql
- ./env/mysql/conf.d:/etc/mysql/conf.d
- ./data/dbimport/:/docker-entrypoint-initdb.d
nr_php72:
build: ./env/php72
hostname: php72
networks:
- mywebapp
depends_on:
- nr_mysql
ports:
- 9000:9000
- 8080:8080
volumes:
- ./env/composer:/home/www/.composer
- ./env/global/bashrc:/home/www/.bashrc
- ./data/bash/.bash_history:/home/www/.bash_history
- ~/.ssh:/home/www/.ssh:ro
- ~/.gitconfig:/home/www/.gitconfig:ro
- ./storage:/home/www/storage/mywebapp
- ./src:/home/www/mywebapp/src
Questions
Should the nginx-proxy replace my existing "nr_nginx" container?
Do I have remove the 80:80, 433:433 port mapping for "nr_nginx" and instead assign a random unique port of my choice e.g. 5000?
If yes to question 2, how do I tell the nginx-proxy to proxy pass to my container of port 5000?
Okay, so I think I have solved it:
No it shouldn't replace your own nginx configuration
Yes, remove ports 80 and 443 as this wil be handled by the nginx-proxy, rather expose the ports in your container.
You do not require manually configuring proxy_pass as nginx-proxy does this for you, so long as you specify a VIRTUAL_PORT environment variable.
Here is the boilerplate code that worked for me:
Boilerpalte nginx-proxy-letsencrypt-companion
docker-compose.yml:
version: "3"
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./env/nginx/certs:/etc/nginx/certs
- ./env/nginx/vhost.d:/etc/nginx/vhost.d
- ./env/nginx/share:/usr/share/nginx/html
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: letsencrypt
volumes:
- ./env/nginx/certs:/etc/nginx/certs
- ./env/nginx/vhost.d:/etc/nginx/vhost.d
- ./env/nginx/share:/usr/share/nginx/html
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- NGINX_PROXY_CONTAINER=nginx-proxy
networks:
default:
external:
name: nginx-proxy
Boilerplate Nginx PHP MySQL Environment
docker-compose.yml
version: '3.1'
services:
nginx:
container_name: nginx
build: ./env/nginx
ports:
- 5000:5000
expose:
- 80
- 443
environment:
- VIRTUAL_HOST=your.domain.com,www.your.domain.com
- VIRTUAL_PORT=5000
- LETSENCRYPT_EMAIL=your#email.com
- LETSENCRYPT_HOST=your.domain.com
depends_on:
- php72
tty: true
volumes:
- ./src:/home/www/webapp/src
- ./storage:/home/www/storage/webapp
- ./data/nginx/logs:/var/log/nginx
- ./env/nginx/webserver/nginx.conf:/etc/nginx/nginx.conf
- ./env/nginx/webserver/conf.d:/etc/nginx/conf.d
- ./env/nginx/webserver/defaults:/etc/nginx/defaults
- ./env/nginx/webserver/global:/etc/nginx/global
- /var/run/docker.sock:/tmp/docker.sock:ro
mysql:
container_name: mysql
build: ./env/mysql
ports:
- 3306:3306
env_file:
- ./env/mysql/.env
volumes:
- ./data/mysql:/var/lib/mysql
- ./env/mysql/conf.d:/etc/mysql/conf.d
- ./data/dbimport/:/docker-entrypoint-initdb.d
php72:
container_name: php72
build: ./env/php72
hostname: php72
depends_on:
- mysql
ports:
- 9000:9000
volumes:
- ./env/composer:/home/www/.composer
- ./env/global/bashrc:/home/www/.bashrc
- ./data/bash/.bash_history:/home/www/.bash_history
- ~/.ssh:/home/www/.ssh:ro
- ~/.gitconfig:/home/www/.gitconfig:ro
- ./storage:/home/www/storage/webapp
- ./src:/home/www/webapp/src
networks:
default:
external:
name: nginx-proxy
/etc/nginx/conf.d/default.conf - inside "nginx" container:
server {
listen 5000;
listen [::]:5000;
server_name www.your.domain.com;
root /my/web/root/src;
index index.php;
include /any/conf/includes/here.conf;
location / {
fastcgi_param HTTPS 'on';
try_files $uri $uri/ /index.php$is_args$args;
}
}
The fastcgi_param HTTPS 'on'; conf prevents a redirect loop, you can alternatively add $_SERVER['HTTPS'] = 'on'; to your index.php
I’m having trouble with docker-compose and nginx. First, I have this docker-compose.yml:
services:
nginx:
build: ./nginx
ports:
- '8080:80'
depends_on:
- web
- api
web:
build: ./web
depends_on:
- api
api:
build: ./api
Both web (port 3000) and api (port 8000) are express servers that return WEB and API respectively. Now, inside ./nginx:
# Dockefile
FROM nginx:alpine
COPY ["default.conf", "/etc/nginx/conf.d/"]
EXPOSE 80
# default.conf
server {
location / {
proxy_pass http://web:3000;
}
location /api {
proxy_pass http://api:8000;
}
}
Now, when I go to http://localhost:8080, I get WEB, but when I go to http://localhost:8080/api, it redirects to http://localhost:1337/api/ and I get nothing (by the way, it throws a 304 error)
However, when I write this default.conf (put api in /)
# default.conf
server {
location / {
proxy_pass http://api:8000;
}
location /api {
proxy_pass http://web:3000;
}
}
I get the same result but in / I get API, so both servers work.
I don't know whether it helps you or not. I am using nginx docker image directly in my docker-compose.
for example.
docker-compose.yml
version: '3'
services:
jobsaf-server:
build:
context: .
dockerfile: Dockerfile.production
container_name: jobsaf-server
ports:
- "3000:3000"
- "5858:5858"
- "35729:35729"
- "6379:6379"
environment:
- NODE_ENV=production
networks:
- front-tier
- back-tier
depends_on:
- "redis"
- "mongo"
links:
- mongo
- redis
volumes:
- ./server:/var/www/app/jobsaf-website/server
nginx:
image: nginx:stable
depends_on:
- jobsaf-server
links:
- jobsaf-server
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
ports:
- "0.0.0.0:80:80"
mongo:
image: mongo:latest
container_name: mongo
volumes:
- "db-data:/data/db"
environment:
- MONGO_INITDB_ROOT_USERNAME=${DB_USER}
- MONGO_INITDB_ROOT_PASSWORD=${DB_PASS}
- MONGO_INITDB_DATABASE=admin
ports:
- "0.0.0.0:27017:27017"
networks:
- back-tier
redis:
image: redis
container_name: redis
networks:
- back-tier
volumes:
db-data:
# - /data/db
networks:
front-tier:
back-tier:
I have a digital ocean droplet. In the root of it are the following files
apps/
-main/
-index.html
nginx.conf
docker-compose.yml
My docker-compose.yml file has the following
version: '3'
networks:
proxy:
external: true
internal:
external: false
services:
traefik:
image: traefik:alpine
ports:
- "8080:8080"
- "80:80"
- "443:443"
restart: always
labels:
- logLevel="DEBUG"
- "traefik.backend=monitor"
- "traefik.frontend.rule=Host:monitor.domain.com"
- "traefik.port=8080"
- "traefik.frontend.entryPoints=http,https"
- "traefik.enable=true"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./traefik.toml:/traefik.toml"
- "./acme.json:/acme.json"
expose:
- "8080"
networks:
- internal
- proxy
custom-badge:
image: user/app
environment:
PORT: 3000
ports:
- "3000:3000"
labels:
- traefik.enabled=true
- traefik.backend=app
- traefik.frontend.rule=Host:app.domain.com
- traefik.docker.network=proxy
- traefik.port=3000
networks:
- internal
- proxy
server:
image: nginx:alpine
labels:
- traefik.enabled=true
- traefik.backend=
- traefik.frontend.rule=Host:domain.com
- traefik.docker.network=proxy
- traefik.port=80
volumes:
- "./apps:/etc/nginx/html:ro"
- "./nginx.conf:/etc/nginx/nginx.conf:ro"
command: [nginx-debug, '-g', 'daemon off;']
depends_on:
- traefik
and my nginx.conf
events {
worker_connections 1024; ## Default: 1024
}
http {
server {
listen 80;
server_name domain.com www.domain.com;
location / {
root /etc/nginx/html/main;
proxy_pass domain.com:8080/;
}
}
}
Problem is, when I run docker-compose up everything starts up and I can see all 3 containers started but when I go to domain.com I am not seeing my index.html file. What have I done wrong ?
The other domains work fine: app.domain.com & monitor.domain.com which makes me think it must be something wrong with the nginx config and what files need to be served.
You have a loop - remove proxy_pass. Nginx should serve the data from root folder, not proxy the requests to another service.