I am trying to create a boilerplate project with docker, php & nginx.
After I run build & up commands, I'm trying to access localhos:8080 (my exposed port on nginx), but I get this error in logs:
[crit] 24#24: *1 open() "/var/www/app/public/" failed (13: Permission
denied), client: 127.0.0.1, server: api.boilerplate.local, request:
"GET / HTTP/1.1", host: "localhost:8080" 2020/11/21 [error] 24#24: *1
connect() failed (111: Connection refused) while connecting to
upstream, client: 127.0.0.1, server: api.boilerplate.local, request:
"GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9001", host:
"localhost:8080"
This is my docker-compose.yml:
version: "3.8"
services:
db:
image: mysql
command: ["--default-authentication-plugin=mysql_native_password"]
restart: unless-stopped
ports:
- 3306:3306
env_file:
- ${PATH_CORE}/.env
volumes:
- mysql:/var/lib/mysql
networks:
- backend
api:
build: ${PATH_CORE}/docker/api
restart: unless-stopped
depends_on:
- db
env_file:
- ${PATH_CORE}/.env
volumes:
- ${PATH_CORE}:/var/www/app
networks:
- backend
- frontend
nginx:
build: ${PATH_CORE}/docker/nginx
restart: unless-stopped
depends_on:
- api
ports:
- 8080:80
volumes:
- ${PATH_CORE}/public:/var/www/app/public
networks:
- backend
volumes:
mysql:
networks:
frontend:
backend:
This is my nginx Dockerfile:
FROM nginx:alpine
COPY nginx.conf /etc/nginx/
COPY default.conf /etc/nginx/conf.d/default.conf
RUN apk add shadow && set -x && usermod -u 1000 nginx && groupmod -g 1000 nginx
WORKDIR /etc/nginx/
EXPOSE 80 443
And default.conf file:
server {
listen 80;
server_name api.boilerplate.local;
root /var/www/app/public;
location / {
try_files $uri #rewriteapp;
}
location #rewriteapp {
rewrite ^(.*)$ /index.php/$1 last;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass api:9001;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}
What do I do wrong?
PS: I'm using Fedora and podman
Your nginx container fails to bind to the port 80 as this is a privileged port and requires a super user rights. Simply change the port number to 8080 and update the compose file to match the new port mapping.
And note, that you need to adjust selinux settings when passing volumes on selinux enabled systems.
Related
This is my first web stack using Docker with Nginx - PHP - MariaDB phpmyadmin for my side projects.
Everything work perfectly. But im confusing a bit about my phpmyadmin.
I noticed that when i login to phpmyadmin, why phpmyadmin pop-up a host-address behind my username?
Example: I have username call "test" - when i login to myadminphp , it show up error below
mysqli::real_connect(): (HY000/1045): Access denied for user 'test'#'192.168.0.4' (using password: YES)
When i create the user in mariadb terminal, it give me test#localhost, not test'#'192.168.0.4' .
By using
CREATE USER 'test'#'localhost';
Give my test#localhost user with full permission
GRANT ALL ON my_db.* TO 'test'#'localhost';
FLUSH PRIVILEGES;
And i can login as user by using mysql -u test -p
That im confusing here.
What is occured in my case? Can i switch from 'test'#'192.168.0.4' to test#localhost in PHPmyadmin?
Docker-compose.yml
version: '3.9'
services:
web:
image: nginx:latest
restart: 'always'
ports:
# Use port 80
- "80:80"
# Copy default config file to default folder
# By using volumes keywords
volumes:
- /home/hoangtho/Projects/:/usr/share/nginx/html/
- ./nginx.conf:/etc/nginx/conf.d/default.conf
php:
image: php:7.3-fpm-alpine
restart: "always"
build:
context: './php/'
volumes:
- /home/hoangtho/Projects/:/usr/share/nginx/html/
# PHP
mariadb:
image: mysql
restart: "always"
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- "3306:3306"
# PHPMYADMIN
phpmyadmin:
image: phpmyadmin
restart: always
volumes:
- ./mysql:/var/lib/mysql
environment:
PMA_ARBITRARY: 1
PMA_HOST: mariadb
PMA_HOSTS: localhost,127.0.0.1
ports:
- "81:80"
Nginx.conf
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /usr/share/nginx/html;
autoindex on;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Dockerfile
FROM php:7.3-fpm-alpine
RUN docker-php-ext-install mysqli
The reason this happens is because MySQL returns the error message based on how you're connecting to the server. When you connect to 'localhost' it uses sockets and when you connect through any other host (including 127.0.0.1) it uses TCP/IP networking. MySQL/MariaDB users require a host field, which can be localhost, an IP address or hostname, or the wildcard operator %. The catch is that the wildcard operator does not include localhost connections.
Since you are connecting to a database that is not running on the same server as phpMyAdmin, your connection is not through localhost, so your user cannot have the host field of 'locahost'. Switching to test#localhost will not work because the connection is not local due to how Docker networking functions.
The other part of the problem here is that you're telling phpMyAdmin to connect to three servers, mariadb, localhost, and 127.0.0.1, which is odd and probably not needed. Based on what you've described, you should completely remove the array PMA_HOSTS from your docker-compose.yml and keep the PMA_HOST: mariadb.
So tweak your PMA_HOSTS and change your user to be #'%' or #'192.168.0.4', that should resolve these problems.
I have the following 4 containers:
php-fpm for Laravel API backend
node.js container for the Next.js frontend
nginx container
mysql container
I am able to call the Laravel API and get the correct JSON data from Postman using http://localhost:8088/api/products , but when I try from the Node container, I get FetchError: request to http://localhost:8088/api/ failed, reason: connect ECONNREFUSED 10.0.238.3:8088. I am not sure if it's the nginx configuration issue, or docker-compose.yml configuration issue.
I also tried to call the API from the node container using several other options (none of them worked):
http://php:8088/api/products
http://localhost:8088/api/products
http://php:9000/api/products - gives a different error: FetchError: request to http://php:9000/api/products/ failed, reason: read ECONNRESET
This is the docker-compose.yml:
networks:
laravel:
driver: bridge
services:
nginx:
image: nginx:stable-alpine
container_name: nginx
ports:
- "8088:80"
volumes:
- ./laravel-app:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
- mysql
- node
networks:
- laravel
mysql:
image: mysql
container_name: mysql
restart: unless-stopped
tty: true
ports:
- "4306:3306"
volumes:
- ./mysql:/var/lib/mysql
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: password
SERVICE_TAGS: dev
SERVICE_NAME: mysql
networks:
- laravel
php:
build:
context: .
dockerfile: Dockerfile
container_name: php
volumes:
- ./laravel-app:/var/www/html
ports:
- "9000:9000"
networks:
- laravel
node:
build:
context: ./nextjs
dockerfile: Dockerfile
container_name: next
volumes:
- ./nextjs:/var/www/html
ports:
- "3000:3000"
- "49153:49153"
networks:
- laravel
And this is the nginx default.conf file:
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri = 404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
If you want to reach your Laravel API from the node service, you must use http://nginx/your_api_endpoint.
Nginx acts as a reverse proxy here, it takes the traffic on the port 80 (listen 80;) and redirects it to your Laravel container (fastcgi_pass php:9000;).
So your target is not the Laravel container itself, it is nginx.
http://nginx/api/products/ should works if everything else is ok.
Can't resolve site nginx host inside docker nginx (and other in same network) container.
➜ dockerised-php git:(master) ✗ tree .
.
├── code
│ └── index.php
├── docker-compose.yml
├── README.md
└── site.conf
1 directory, 4 files
site.conf:
server {
listen 80;
index index.php index.html;
server_name docker-test.loc;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /code;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
docker-compose
version: '2'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./code:/code
- ./site.conf:/etc/nginx/conf.d/default.conf
networks:
- code-network
php:
image: php:fpm
volumes:
- ./code:/code
networks:
- code-network
networks:
code-network:
docker-test.loc resolving from browser, but
docker exec -it dockerised-php_web_1 bash
nslookup docker-test.loc
# connection timed out; no servers could be reached
outside
➜ ~ nslookup docker-test.loc
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: docker-test.loc
Address: 127.0.0.1
docker container resolver:
➜ ~ docker exec -it dockerised-php_web_1 bash
root#6340952094ed:/# cat /etc/resolv.conf
search Dlink
nameserver 127.0.0.11
options ndots:0
I tried cat "127.0.0.1 docker-test.loc" >> /etc/hosts inside nginx container but it not helps.
What should I do to resolve docker-test.loc inside container?
You can edit docker-compose.yml file to add container_name for web service like that:
version: '2'
services:
web:
image: nginx:latest
ports:
- "8080:80"
container_name: docker-test.loc
volumes:
- ./code:/code
- ./site.conf:/etc/nginx/conf.d/default.conf
networks:
- code-network
php:
image: php:fpm
volumes:
- ./code:/code
networks:
- code-network
networks:
code-network:
Then all container in the code-network can resolve docker-test.loc as IP address of your web-service container in your docker compose.
EDIT
For more than one hostname(virtualhost) in your nginx container you can use external_links like that:
version: '2'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./code:/code
- ./site.conf:/etc/nginx/conf.d/default.conf
networks:
- code-network
php:
image: php:fpm
volumes:
- ./code:/code
networks:
- code-network
external_links:
- web:docker-test__1.loc
- web:docker-test__2.loc
- web:abcdef.vn
networks:
code-network:
Thanks.
I am trying to containerize all things related to my web app using Docker Compose, including Nginx & SSL Certificates. To do this I am using the Nginx Proxy image from JWilder and the LetsEncrypt Companion, but am having trouble getting the nginx proxy to work, result ends up being:
Nginx 502 Bad Gateway
[error] 31160#0: *35 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xx.xx, server: domain.com, request: "GET /dev/ HTTP/1.1", upstream: "webapp://127.0.0.1:8080", host: "domain.com"
This only happened when trying to set up the Nginx proxy and SSL certificates so I know it's a configuration issue for either or both of these containers. If anyone can spot where I am going wrong, I would be extremely grateful!
Here are the containers in question:
version: '3.1'
networks:
mywebapp:
services:
nginx-proxy:
container_name: nginx-proxy
build: ./env/nginx-proxy
networks:
- mywebapp
ports:
- 80:80
- 443:443
env_file:
- ./env/nginx-proxy/.env
depends_on:
- webapp
tty: true
volumes:
- ./src:/home/www/mywebapp/src
- ./storage:/home/www/storage/mywebapp
- ./data/nginx-proxy/logs:/var/log/nginx
- ./env/nginx-proxy/webserver/nginx.conf:/etc/nginx/nginx.conf
- ./env/nginx-proxy/webserver/conf.d:/etc/nginx/conf.d
- ./env/nginx-proxy/webserver/vhost.d:/etc/nginx/vhost.d
- ./env/nginx-proxy/webserver/defaults:/etc/nginx/defaults
- ./env/nginx-proxy/webserver/global:/etc/nginx/global
- ./env/nginx-proxy/ssl/certs:/etc/nginx/certs
- ./env/nginx-proxy/share:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
letsencrypt:
restart: always
container_name: letsencrypt
image: jrcs/letsencrypt-nginx-proxy-companion
env_file:
- ./env/letsencrypt/.env
volumes:
- ./data/letsencrypt/logs:/var/log
- ./env/nginx-proxy/webserver/nginx.conf:/etc/nginx/nginx.conf
- ./env/nginx-proxy/webserver/conf.d:/etc/nginx/conf.d
- ./env/nginx-proxy/webserver/vhost.d:/etc/nginx/vhost.d
- ./env/nginx-proxy/webserver/defaults:/etc/nginx/defaults
- ./env/nginx-proxy/webserver/global:/etc/nginx/global
- ./env/nginx-proxy/ssl/certs:/etc/nginx/certs
- ./env/nginx-proxy/share:/usr/share/nginx/html
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- nginx-proxy
webapp:
container_name: webapp
build: ./env/webapp
hostname: webapp
networks:
- mywebapp
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
Key points being:
Webapp is the source of my web application which is running PHP, MySQL and Nginx webserver. The webapp webserver exposes and listens on port 8080 to serve the PHP files.
Nginx proxy exposes standard ports 443 and 80 and proxy passes to webapp on port 8080
LetsEncrypt Companion generates the certs and renews.
Nginx Proxy server configuration:
upstream webapp {
server 127.0.0.1:8080;
}
server {
listen 80;
listen [::]:80;
server_name webapp.localhost;
location / {
proxy_pass http://webapp;
}
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate certs/default.crt;
ssl_certificate_key certs/default.key;
include /etc/nginx/global/ssl-params.conf;
server_name webapp.localhost;
location / {
proxy_pass http://webapp;
}
}
Webapp webserver configuration:
server {
listen 8080;
listen [::]:8080;
server_name webapp.localhost;
root /home/www/webapp/src;
index index.php;
include /etc/nginx/defaults/php.conf;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
}
When visiting http://webapp.localhost:8080 I can see the webapp webserver serves the page no trouble, so I suspect it's something wrong with my Nginx Proxy server configuration.
Thanks for reading.
Since nginx and webapp are on two separate containers, nginx can't reach webapp on localhost(127.0.0.1) as you've configured for upstream:
upstream webapp {
server 127.0.0.1:8080;
}
Change it to webapp:8080.
i want to create a LEMP stack with docker-compose for local web development but i've got in some troubles...
The configuration files i wrote:
docker-compose.yml
nginx:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./web:/web
- ./mysite.template:/etc/nginx/conf.d/mysite.template
links:
- php
command: /bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
php:
image: php:7-fpm
volumes:
- ./web:/web
mysite.template
server {
listen 80;
root /web;
index index.php index.html;
server_name default_server;
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /web$fastcgi_script_name;
}
}
The problem is that when i try to open http://localhost:8080 the result is an Access Denied
How can i fix it?
EDIT:
This is the nginx container error log:
nginx_1 | 2017/11/01 13:21:25 [error] 8#8: *1 FastCGI sent in stderr: "Access to the script '/web' has been denied (see security.limit_extensions)" while reading response header from upstream
I was able to get your example working by changing your docker-compose.yml to:
nginx:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./web:/web
- ./mysite.template:/etc/nginx/conf.d/default.conf
links:
- php
php:
image: php:7-fpm
volumes:
- ./web:/web