How to create a LEMP stack with docker-compose? - docker

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

Related

Can't call my Laravel API from the Node.js container but I can call it from Postman

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.

Docker compose nginx permissions problem using fedora and podman

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.

resolve site hostname inside docker container

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.

Error - nginx: [emerg] "server" directive is not allowed here in /etc/nginx/nginx.conf:1

I created a docker-compose.yml file with Nginx, PHP-7.4-fpm, PhpMyAdmin and MariaDB, the execution of my docker-compose.yml has been deployed successfully but the Nginx container has an error:
nginx: [emerg] "server" directive is not allowed here in /etc/nginx/nginx.conf:1
.docker/docker-compose.yml:
version: '3'
services:
nginx:
image: nginx:alpine
volumes:
- ../:/code
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./logs:/var/log/nginx
ports:
- "80:80"
depends_on:
- php
php:
build:
context: './config/php/'
args:
PHP_VERSION: ${PHP_VERSION}
depends_on:
- mariadb
volumes:
- ../:/code
- ./config/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
ports:
- "9000:9000"
mariadb:
image: mariadb:${MARIADB_VERSION}
restart: always
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=${MARIADB_DATABASE}
- MYSQL_USER=${MARIADB_USER}
- MYSQL_PASSWORD=${MARIADB_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
volumes:
- ./database:/var/lib/mysql
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- "${PHPMYADMIN_HTTP_PORT}:80"
depends_on:
- mariadb
environment:
- MYSQL_USER=${MARIADB_DATABASE}
- MYSQL_PASSWORD=${MARIADB_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
.docker/config/nginx/nginx.conf:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name monsite.local;
root /code;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
error_log /var/log/nginx/project_error.log;
access_log /var/log/nginx/project_access.log;
}
I don't understand why I have this error, can you help me please ?
Thank you in advance
In your context you need to wrap server in http block. Or move you config file not by replacing the default config file, but rather replacing a default server config located in /etc/nginx/conf.d/ So you can use something like
- ./nginx.conf:/etc/nginx/conf.d/default.conf
for volumes for nginx. That will rewrite your default server config.
You can also copy it to sites-enabled folder if you planning to use multiple config files.
Or you can modify your nginx config, by starting with wrapping it with http block

Ngnix and docker compose - not return static files

This is my docker-file.yml
version: '2'
services:
nginx:
image: nginx:latest
ports:
- '80:80'
- '443:443'
volumes:
- ./conf.d:/etc/nginx/conf.d/
- ./logs/nginx_access.log:/var/log/nginx_access.log
- ./logs/nginx_error.log:/var/log/nginx_error.log
- ./src/app/static:/flask-app/src/app/static
depends_on:
- web
web:
build: ./
command: gunicorn manage:app --bind 0.0.0.0:8000 --access-logfile=logs/gunicorn_access_log.txt
ports:
- '8000:8000'
volumes:
- ./:/flask-app
environment:
DATABASE_URL: postgresql://postgres:pass#localhost/flask_deploy
REDIS_HOST: redis
SECRET_KEY: 'BbGd3qe$dsf1'
CONFIG_NAME: 'prod'
links:
- postgres:postgres
- redis:redis
depends_on:
- postgres
- redis
postgres:
image: postgres:9.4
volumes:
- ./psql-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: 'pass'
POSTGRES_DB: 'flask_deploy'
ports:
- '5432:5432'
redis:
image: "redis:3.0-alpine"
command: redis-server
ports:
- '6379:6379'
And this is my ngnix config (web is name from docker-compose file) :
server {
listen 80;
server_name web;
# запись доступа и журналы ошибок в /var/log
access_log /var/log/nginx_access.log;
error_log /var/log/nginx_error.log;
location / {
# переадресация запросов приложений на сервер gunicorn
proxy_pass http://web:8000;
}
location /static {
# обрабатывать статические файлы напрямую, без пересылки в приложение
autoindex on;
alias /flask-app/src/app/static;
expires 1d;
}
}
And my site avaliable on 127.0.0.1 (without port). But.. I have trouble with static files. Flask url_for generate url like:
http://web:8000/static/img/do.jpg
And this link unavailable.
I can try this:
http://127.0.0.1:8000/static/img/do.jpg
And i saw picture. But this picture returned by gunicorn, not ngnix :(
I am beginner in docker-compose and ngnix. Maybe, some comments about my config? Thanks!
Solution:
proxy_set_header Host $host:8000;
Full config:
server {
listen 80;
server_name localhost;
root /flask-app/src/app;
access_log /var/log/nginx_access.log;
error_log /var/log/nginx_error.log;
location / {
proxy_set_header Host $host:8000;
proxy_pass http://web:8000;
}
location /static {
autoindex on;
expires 1d;
}
}

Resources