I'm a new user of Docker. What I want to do is to setup (on my Windows PC) the Docker platform with a nginx server and a slim framework on this server, so that I be able to "host" a simple "hello world" page.
My question is: should I create a container containing the Nginx and inside that container install the Slim framework?
Or should i create two different containers (one for Nginx, one for Slim). And if so, how those two communicate?
Anyway whatever the solution is, first I would like to understand the "architecture" of this "build" and after that how to do it.
Thanks in advance
You can use two containers, using docker-compose to connect slim and nginx, something like this:
docker-compose.yaml
version: "3.8"
services:
php:
container_name: slim
build:
context: ./docker/php
ports:
- '9000:9000'
volumes:
- .:/var/www/slim_app
nginx:
container_name: nginx
image: nginx:stable-alpine
ports:
- '80:80'
volumes:
- .:/var/www/slim_app
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
DOCKERFILE in ./docker/php
FROM php:7.4-fpm
RUN docker-php-ext-install ALL_YOUR EXTENSIONS
WORKDIR /var/www/slim_app
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
Docker nginx in /docker/nginx/default.conf
server {
listen 80;
index index.php;
server_name localhost;
root /var/www/slim_app/public;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\\.php(/|$) {
fastcgi_pass php:9000;
fastcgi_split_path_info ^(.+\\.php)(/.*)$;
internal;
}
location ~ \\.php$ {
return 404;
}
}
Just execute the containers
docker-compose up -d
go to http://localhost/
Related
I have two docker-compose.yml files
THe first one is a global one and am using it to configure nginx webserver and the other one am using it for holding the application code and below are their configurations
First one with nginx configuration
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: globaldocker
container_name: app
restart: unless-stopped
tty: true
working_dir: /var/www
volumes:
- ./:/var/www
- ./dockerconfig/php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- common_network
webserver:
image: nginx
container_name: webserver
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www
- ./dockerconfig/nginx/:/etc/nginx/conf.d/
networks:
- webserver_network
- common_network
networks:
common_network:
external: false
webserver_network:
external: false
The above creates two networks
global_docker_common_network, global_docker_webserver_network
On the docker config folder there is a nginx configuration like
server {
listen 80;
server_name pos.test www.pos.test;
index index.php index.html;
//other nginx configurations for pos.test
}
ON THE docker-compose configuration with php file
Now the one one holding the source code for pos.test i have the following configuration
app:
build:
context: .
dockerfile: Dockerfile
image: posapp/php
container_name: envanto_pos
restart: unless-stopped
tty: true
working_dir: /var/www/pos
volumes:
- ./:/var/www/pos
- ./dockerconfig/nginx/:/etc/nginx/conf.d/
networks:
- globaldocker_webserver_network
networks:
globaldocker_webserver_network:
external: true
Which i have added the external network
When i try accessing nginx pos.test it doesnt display the application but only shows the default nginx page
I have tried accessing the first docker nginx configuration bash and checked on the var/www/pos folder but i cant see the files from the second docker config(source code).
How do i share volumes with my nginx docker configuration container so that when i access docker via exposed port 80 am able to access my site pos.test
What am i missing out on this to make this work?
UPDATE
The two docker configuration files are located on different folders on my host machine
UPDATE ON THE QUESTION
This is my nginx config file
server {
listen 80;
server_name pos.test www.pos.test;
index index.php index.html;
error_log /var/log/nginx/pos_error.log;
access_log /var/log/nginx/pos_access.log;
root /var/www/pos/web;
location ~ \.php$ {
try_files $uri =404;
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;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}
you are mounting the current directory of docker-compose file each. So the only that container will have the source code which resides in the same source code directory.
You need some common directory
First File
volumes:
- /path_to_sc/common:/var/www
Second File
volumes:
- /path_to_sc/common:/var/www/pos
When I try accessing Nginx pos.test it doesn't display the application
but only shows the default Nginx page
Probably you first File not picking correct configuration. Double-check ./dockerconfig/nginx/:/etc/nginx/conf.d/ or run the command inside docker to verify the correct configuration file.
docker exec nginx bash -c "cat /etc/nginx/conf.d/filename.conf`
I have tried accessing the first docker nginx configuration bash and
checked on the var/www/pos folder but i cant see the files from the
second docker config(source code).
Mount the common directory so that can accessible for both containers.
update:
From your comment, it seems like there is a syntax error in your docker-compose file. Take a look into this example
web:
image: nginx
volumes:
- ./data:/var/www/html/
ports:
- 80:80
command: [nginx-debug, '-g', 'daemon off;']
web2:
image: nginx
volumes:
- ./data:/var/www/html
command: [nginx-debug, '-g', 'daemon off;']
I'm trying to use docker ( first time at all ) to build a development env for my laravel projects.
I have read the documentation and looks like that docker-compose.yml file is the way to go, at least in my case.
I'm trying to create a LEMP env and this is my compose file:
version: "3.1"
services:
memcached:
image: memcached:alpine
container_name: 01dev-memcached
mysql:
image: mysql:8.0
container_name: 01dev-mysql
working_dir: /application
volumes:
- ./:/application
environment:
- MYSQL_ROOT_PASSWORD=laravel
- MYSQL_DATABASE=laravel
- MYSQL_USER=laravel
- MYSQL_PASSWORD=laravel
ports:
- "8082:3306"
webserver:
image: nginx:alpine
container_name: 01dev-webserver
working_dir: /application
volumes:
- ./:/application
- ./phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- "8080:80"
php-fpm:
build: phpdocker/php-fpm
container_name: 01dev-php-fpm
working_dir: /application
volumes:
- ./:/application
- ./phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/7.3/fpm/conf.d/99-overrides.ini
My nginx.conf file:
server {
listen 80 default;
client_max_body_size 108M;
access_log /var/log/nginx/application.access.log;
root /application/public;
index index.php;
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
location ~ \.php$ {
fastcgi_pass php-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;
}
}
since is a Laravel application I need to set the public folder as root, so in my nginx.conf I have set it.
If I manually create the public folder with a index.php with just a echo "hello"; I'm able to connect and see the string on http://localhost:8080.
Now I need to use composer to install and to manage my project so I found a composer image and I have added it under services in docker-compose.yml:
composer:
restart: 'no'
container_name: 01dev-composer
image: "composer"
command: install
volumes:
- ./:/application
As far as I know with volumes I bind my host to the container path, so it should point outside the public folder, am I right?
If I run docker-compose up I see that the composer container exit with code 1:
01dev-composer | Composer could not find a composer.json file in /app
01dev-composer | To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
01dev-composer exited with code 1
And I'm not able to connect to it:
docker-compose exec composer install
ERROR: No container found for composer_1
How can I use composer in my project? There is a better way to do that?
See composer Dockerfile:
WORKDIR /app
This image's working dir is /app, and also from the guide, all example mount code directory to the /app folder in container.
Besides, the error also tells you that:
Composer could not find a composer.json file in /app
So, the thing you need to do is mount your code directory to /app & make sure this service start first, then it will generate vendor folder in your source code directory:
volumes:
- ./:/app
I have a docker with 2 containers for serving individual sites and jwilder/nginx-proxy in front of them.
However I'm only getting the default nginx page, so the vhosts aren't routing correctlty.
I've used https://www.rent-a-hero.de/wp/2017/06/09/use-j-wilders-nginx-proxy-for-multiple-docker-compose-projects/ as a guide t get myself started on this, because I wanted to set up a proxy network.
Each of the serving nxinx containers has a vhost file, and uses a 4th, shared php container (the code is the same in both nginx containers).
$ docker run -d \
--name nginx-proxy \
-p 80:80 \
--network=nginx-proxy \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy
/docker-compose.yml
version: '2'
services:
app-admin:
image: nginx:latest
container_name: app-admin
environment:
VIRTUAL_HOST: admin.app.local
VIRTUAL_PORT: 80
volumes:
- .:/var/www/html
- admin.app.conf:/etc/nginx/vhost.d/admin.app.local:ro
links:
- php
php:
image: php:7-fpm
container_name: php
volumes:
- .:/var/www/html
networks:
default:
external:
name: nginx-proxy
/admin.app.conf:
server {
server_name admin.app.local
listen 80;
listen [::]:80;
root /var/www/html;
index index.html index.php;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ /\.ht {
deny all;
}
}
app.conf is essentially the same for this testing stage... same result
Original files edited to help simplify the question (the removed files just basically setup the required nginx-proxy container and network, and I;ve stripped out the example second nginx container)
I configured my django-uwsgi-nginx using docker compose with the following files.
From browser "http://127.0.0.1:8000/" works fine and gives me the django default page
From browser "http://127.0.0.1:80" throws a 502 Bad Gateway
dravoka-docker.conf
upstream web {
server 0.0.0.0:8000;
}
server {
listen 80;
server_name web;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
alias "/dravoka-static/";
}
location / {
include uwsgi_params;
proxy_pass http://web;
}
}
nginx/Dockerfile
FROM nginx:latest
RUN echo "---------------------- I AM NGINX --------------------------"
RUN rm /etc/nginx/conf.d/default.conf
ADD sites-enabled/ /etc/nginx/conf.d
RUN nginx -t
web is just from "django-admin startproject web"
docker-compose.yaml
version: '3'
services:
nginx:
restart: always
build: ./nginx/
depends_on:
- web
ports:
- "80:80"
web:
build: .
image: dravoka-image
ports:
- "8000:8000"
volumes:
- .:/dravoka
command: uwsgi /dravoka/web/dravoka.ini
Dockerfile
# Ubuntu base image
FROM ubuntu:latest
# Some installs........
EXPOSE 80
When you say from the docker instance , you are running curl from with in the container ?? or you are running the curl command from your local ?
if you are running it from your local , update your docker-compose's web service to following
...
web:
build: .
image: dravoka-image
expose:
- "8000:8000"
volumes:
- .:/dravoka
command: uwsgi /dravoka/web/dravoka.ini
and try again.
I'm new to docker and trying the simplest docker-compose.yml showing an hello world page to build on top of that with eventually a full LEMP stack that would have the same config as my server. However most tutorials are obsolete and there are so many ways of using docker that I can't find one using only Docker compose v3 that is still actual. I checked the docs and it's awfully confusing as well for a beginner, been trying to make it work for the past 5 hours so I thought I'd ask on SO.
docker-compose.yml
version: '3'
services:
web:
image: bitnami/nginx:1.10.3-r0 #using this version as it's the same on my server
volumes:
- "./test.conf:/etc/nginx/sites-available/test.local"
- "./test.conf:/etc/nginx/sites-enabled/test.local"
- "./code:/var/www/html" #code contains only a basic index.html file
ports:
- "80:80"
test.conf
server {
listen 80;
listen [::]:80;
server_name test.local;
index index.html; #Only a basic helloworld index.html file
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html;
}
Do I need a Dockerfile with this? Tutorials don't seem to mention it's needed.
NOTE:
Tried adding the volume
- "./default.conf:/etc/nginx/conf.d/default.conf"
but nothing changes and the welcome page still loads, while with nginx:latest I get a very verbose error containing this phrase: "unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type".
UPDATE about docker-compose.yml:
Without the line "./code:/usr/share/nginx/html", the /usr/share/nginx/html folder contains the default index.html file (expected)
With the line "./code:/usr/share/nginx/html", the /usr/share/nginx/html folder is EMPTY!
With the line "./:/usr/share/nginx/html", the /usr/share/nginx/html folder has and empty "code" folder and a bunch of random test files I deleted a while ago.
Between tries, I run my reset script to make sure I start fresh:
docker rm $(docker ps -a -q)
docker rmi $(docker images -q) --force
docker volume rm $(docker volume ls -q)
Running docker inspect <container> returns this for the volume, not sure it's normal that the type is "bind" for as a bind mount instead of a volume.
"Mounts": [
{
"Type": "bind",
"Source": "/e/DEV/sandbox/docker",
"Destination": "/usr/share/nginx/html",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
}
],
It's easy to mount your own hello world page. I'll explain it using the official nginx:latest image but you can do it for yourself with the bitnami image if you want.
First the very basic. Just run the nginx container (without docker-compose). I'll explain it in detail and basic, of course I can try to perform more advanced or faster commands to read files which are inside the container but this can be confusing for a beginner. So just run the container and name it my-nginx:
$ docker run --rm -d -p 80:80 --name my-nginx nginx
Go to localhost:80, you'll see the default nginx page.
Now you can exec inside the container by using it's name. exec will bring you 'inside the container' so you can check its files.
$ docker exec -it my-nginx bash
root#2888fdb672a1:/# cd /etc/nginx/
root#2888fdb672a1:/etc/nginx# ls
conf.d koi-utf mime.types nginx.conf uwsgi_params
fastcgi_params koi-win modules scgi_params win-utf
Now read the nginx.conf by using cat.
The most important line in this file is:
include /etc/nginx/conf.d/*.conf;
This means all the confs inside that directory are used/read.
So go into /etc/nginx/conf.d/.
root#2888fdb672a1:~# cd /etc/nginx/conf.d/
root#2888fdb672a1:/etc/nginx/conf.d# ls
default.conf
The default.conf is the only file. Inside this file you see the configuration:
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
server is local host, port is 80 and the file that will be displayed is in the directory /usr/share/nginx/html/
Now check that file in your container:
root#2888fdb672a1:/etc/nginx/conf.d# cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
...
It's the expected file. It's the 'Welcome to Nginx' page we can see.
So how can we show our own index.html? By just mounting it in /usr/share/nginx/html.
You'll docker-compose.yaml will look like this.
version: '3'
services:
web:
image: nginx:latest
volumes:
- ./code:/usr/share/nginx/html
ports:
- "80:80"
The code directory just contains an index.html with hello world.
Run docker-compose up -d --build and when you curl localhost:80 you will see your own index.html.
If you really want to put your code in /var/www/html instead of /usr/share/nginx you can do that.
Use your test.conf. Here you define to put your file in /var/www/html/:
server {
listen 80;
listen [::]:80;
server_name test.local;
index index.html; #Only a basic helloworld index.html file
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html;
}
In the compose you will overwrite the default.conf with your own conf where you tell nginx to look in /var/www/html.
Your compose can look like this:
version: '3'
services:
web:
image: nginx:latest
volumes:
- "./test.conf:/etc/nginx/conf.d/default.conf"
- "./code:/var/www/html"
ports:
- "80:80"
Now you will also see your own index.html while it's on your own specified location. Long answer but I hope this helps.
After struggling a lot on this question, I have figured out three factors that made my deploy with docker-compose work.
I did a website in nodejs.
We expose web part and nginx on port 80
Dockerfile for nodejs : [ important line is -> EXPOSE 80 ]
FROM node:14-alpine
WORKDIR /
COPY package.json ./
EXPOSE 80
RUN npm install
COPY . .
CMD ["node", "bin/www"]
Nginx.conf for nginx : [ important line is -> listen 80; ]
events {
}
http {
server {
listen 80;
location / {
proxy_pass http://nodejs:3000;
}
}
}
We give to nginx config file, the name and port of web's image
docker-compose.yaml :
[ important line is -> image: nodejs ] that is the name of web's image
AND
[ important line is -> ports: -"3000:3000" ] that is the port to run web's part
version: "3.7"
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
networks:
- app-network
ports:
- "3000:3000"
webserver:
image: nginx
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/:/etc/nginx/conf.d
depends_on:
- nodejs
networks:
- app-network
networks:
app-network:
driver: bridge
Nginx.conf for nginx : [ important line is -> proxy_pass http://nodejs:3000; ]
events {
}
http {
server {
listen 80;
location / {
proxy_pass http://nodejs:3000;
}
}
}
We give nginx's image, volumes as path for the config file to replace default one
Tree :
mainfolder
.
|_____nginx
| |______nginx.conf
|
|_____Dockerfile
|
|_____docker-compose.yaml
docker-compose.yaml :
[ important line is -> ./nginx/nginx.conf:/etc/nginx/nginx.conf ] to replace config file
version: "3.7"
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
networks:
- app-network
ports:
- "3000:3000"
webserver:
image: nginx
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
depends_on:
- nodejs
networks:
- app-network
networks:
app-network:
driver: bridge