I'm trying to share code from host to php and nginx containers. Here is my docker-compose.yml:
version: "3"
services:
php:
image: php:fpm
container_name: php
ports:
- 9000:9000
volumes:
- php_data:/var/www/html/
# configs
- ./php/config:/usr/local/etc/php
nginx:
image: nginx
ports:
- 80:80
volumes:
- php_data:/var/www/html
# logs
- ./nginx/logs:/var/log/nginx
# configs
- ./nginx/config/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./nginx/config/nginx.conf:/etc/nginx/nginx.conf:ro
volumes:
php_data:
./code
The error when running docker-compose up is:
ERROR: In file './docker-compose.yml', volume 'php_data' must be a
mapping not a string.
How do I make make docker-compose know, that I need ./code shared with both nginx and php containers?
Docker saying it needs a mapping, so you need to set something like ./code:{map} in your volume
I think you have 2 options here. Since you share the code map to /var/www/html on both containers.
Option 1
Set the /var/www/html map in your volume:
volumes:
php_data:
./code:/var/www/html
then change /var/www/html to / in your containers.
Option 2
volumes:
php_data:
./code:/
Related
I am pretty beginner with Docker, and I'm trying to create a local development LAMP (more exactly Apache, MariaDB, PHP) stack using docker-compose, existing Docker images from Docker hub and no Dockerfile if possible, to be used with several local web projects.
I'd like to map my local web project directory /Users/myusername/projects/myprojectname to the default document root for Apache container (which seems to be /app for the Apache image I'm using)
Here is my docker-compose.yml file:
version: "3"
services:
mariadb:
image: mariadb:10.5
container_name: mariadb
restart: always
ports:
- 8889:3306
volumes:
- ./mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=localmysqluser
- MYSQL_PASSWORD=localmysqlpwd
php:
image: bitnami/php-fpm:7.4
container_name: php
ports:
- 9000:9000
volumes:
- /Users/myusername/projects/myprojectname:/app
apache:
image: bitnami/apache:latest
container_name: apache
restart: always
ports:
- 8080:80
volumes:
- ./apache-vhosts/myapp.conf:/vhosts/myapp.conf:ro
- /Users/myusername/projects/myprojectname:/app
depends_on:
- mariadb
- php
But when I do docker-compose up -d then browse to http://localhost:8080/, I get zero data. Where am I wrong? Is my docker-compose.yml configuration wrong, or is it because of system rights?
I've been looking at this similar question, but I'd prefer not using any Dockerfile if possible.
Further question: is it possible to make a local directory /Users/myusername/projects/ browsable by Apache in my local browser?
As answered by J. Song, exposed port number of this Apache Docker image is 8080, not 80.
So we just need to change port mapping of Apache service to 8080:8080 instead of 8080:80.
I have got following compose file where i'm sharing some generated html data from Jenkins container to the host drive and reading this data by Nginx container from the host drive. I'm using Ubuntu Server 18.04 on AWS.
The problem is that I can read contents of the jenkins/workspace/allure-report only once. After updating of the html data it becomes inaccessible for Nginx and it throws 403 status code.
I tried all the possible solutions but nothing works. The only ugly solution is to restart Nginx container after every html data updating. I don't like this way and looking for some inbuilt docker features to resolve this.
What didn't help: sharing volume straight between containers without using docker host drive, using rslave option, using docker separate volume that can be used as buffer between the two containers... I believe it should be much more easier!
version: '2'
services:
jenkins:
container_name: jenkins
image: "jenkins/jenkins"
ports:
- "8088:8080"
- "50000:50000"
env_file:
- variables.env
volumes:
- ./jenkins:/var/jenkins_home
selenoid:
container_name: selenoid
network_mode: bridge
image: "aerokube/selenoid"
# default directory for browsers.json is /etc/selenoid/
command: -listen :4444 -conf /etc/selenoid/browsers.json -video-output-dir /opt/selenoid/video/ -timeout 3m
ports:
- "4444:4444"
env_file:
- variables.env
volumes:
- $PWD:/etc/selenoid/ # assumed current dir contains browsers.json
- /var/run/docker.sock:/var/run/docker.sock
selenoid-ui:
container_name: selenoid-ui
network_mode: bridge
image: "aerokube/selenoid-ui"
links:
- selenoid
ports:
- "8080:8080"
env_file:
- variables.env
command: ["--selenoid-uri", "http://selenoid:4444"]
nginx:
container_name: nginx
image: "nginx"
ports:
- "80:80"
volumes:
- ./jenkins/workspace/allure-report:/usr/share/nginx/html:ro,rslave
Found the solution: the easiest way to get access to the dynamic data is to use volumes_from in that container you want to look from.
When I configured my compose file like that I faced another issue - the 403 status has gone but the data was static. But that was my fault, I didn't use "cp -r " command correctly so my data has been copied only once.
I'm trying to create an Nginx/PHP FPM setup with docker compose and am having issues with the version 3 volumes syntax/changes.
My Dockerfile:
FROM php:7-fpm
VOLUME /var/www/html
My docker-compose.yml:
version: "3"
services:
php:
build: .
volumes:
- ./html:/var/www/html
web:
image: nginx
links:
- php
ports:
- "8888:80"
volumes:
- php:/var/www/html
- ./default.conf:/etc/nginx/conf.d/default.conf
volumes:
php:
When I add an index.php file into ./html, I can view that by going to http://localhost:8888, but any static files (like CSS) return a 404 because Nginx cannot find those in its container (/var/www/html is empty on the nginx container). With version 3 docker compose files do not have volumes_from anymore, which is basically what I'm trying to replicate.
How can I get this to work with version 3?
For using "Named volumes" for sharing files between containers you need to define
1) volumes: section on the top level of yml file and define volume name
volumes:
php:
2) define volume section on first container like you did (Where share will mount)
web:
volumes:
- php:/var/www/html #<container_name>:<mount_point>
3) define volume section on second container (Share will mount from)
php:
volumes:
- php:/var/www/html
4) (optionally) If you need to store volume data on the host machine you can use local-persist docker plugin. You can specify docker volume driver and path where you data will be stored.
volumes:
php:
driver: local-persist
driver_opts:
mountpoint: /path/on/host/machine/
In your case you forgot define volume name for php container. Just replace
php:
build: .
volumes:
- ./html:/var/www/html
to
php:
build: .
volumes:
- php:/var/www/html
and use Local Persist Docker Plugin
I am trying to understand - maybe I already did maybe not - the differences between volumes_from and volumes usage in a docker-compose.yml file. I have read docs already but from there is not so clear to me so I am doing a real exercise.
I have the following setup:
a root directory
a directory named php-apache with a Dockerfile under root
a directory named mongo with a Dockerfile under root
a docker-compose.yml file under root
Note: If it's not clear to you, take a look here and everything exposed down below is right there as well (mongodb-test branch)
At php-apache/Dockerfile I have the following entry:
VOLUME /data /data
At mongo/Dockerfile I have the following entry:
VOLUME /data/db /data/configdb
At docker-compose.yml I have the following:
version: '2'
services:
php-apache:
container_name: "php55-dev"
image: reynierpm/php55-dev
ports:
- "80:80"
environment:
PHP_ERROR_REPORTING: 'E_ALL & ~E_DEPRECATED & ~E_NOTICE'
volumes:
- ~/mmi:/var/www
volumes_from:
- volumes_data
mongo:
container_name: "mongodb"
image: reynierpm/mongodb
ports:
- "27017:27017"
volumes_from:
- volumes_data
volumes_data:
image: tianon/true
volumes:
- ~/data/mongo:/data/db
- ~/data:/data
This is what I am understanding from that setup:
The image reynierpm/php55-dev will expose a /data directory and this will be mapped to ~data:/data in tianon/true image
The image reynierpm/mongodb will expose a /data/db to the outside and mapped to /data/configdb internally then the /data/db is mapped to ~/data/mongo:/data/db in tianon/true image.
Is a mess in my head right now because what do I want to achieve is the following:
Keep mapped the code on the host to the container (this line <path_on_host>:/var/www on docker-compose.yml)
Keep data stored on a local directory in the host
So, it's fine what I am doing? Feel free to made any modification at this setup since I am still learning.
The image reynierpm/php55-dev will expose a /data directory and this will be mapped to ~data:/data in tianon/true image
It's better to say it will mapped to your ~/data on docker host. Please note that there will be a /data/db from the second volume too.
The image reynierpm/mongodb will expose a /data/db to the outside and mapped to /data/configdb internally then the /data/db is mapped to ~/data/mongo:/data/db in tianon/true image.
This container will be the same as php-apache in terms of volumes from
volume_data container.
In case of your objectives:
If your code is in ~/mni/ you are fine. You are mounting mongoDB database directory to php-apache container, I don't think you need that.
You need to create a user defined network for your container connectivity or link containers (legacy). To create user defined network:
docker network create --driver bridge <yournetwork name>
You don't need a DOC. Thats why I removed the third container. I also fixed the unnecessary volume mappings.
Updated Docker file:
version: '2'
services:
php-apache:
container_name: "php55-dev"
image: reynierpm/php55-dev
ports:
- "80:80"
environment:
PHP_ERROR_REPORTING: 'E_ALL & ~E_DEPRECATED & ~E_NOTICE'
volumes:
- ~/mmi:/var/www
volumes_from:
- volumes_data
mongo:
container_name: "mongodb"
image: reynierpm/mongodb
ports:
- "27017:27017"
volumes_from:
- volumes_data
volumes_data:
image: tianon/true
volumes:
- ~/data/mongo:/data/db
- ~/data:/data
networks:
default:
external:
name: <your network name>
Please note you have to call your mongo container from your web application by its name, in your case mongodb.
I am new to docker and developing a project using docker compose. From the documentation I have learned that I should be using data only containers to keep data persistant but I am unable to do so using docker-compose.
Whenever I do docker-compose down it removes the the data from db but by doing docker-compose stop the data is not removed. May be this is because that I am not creating named data volume and docker-compose down hardly removes all the containers. So I tried naming the container but it threw me errors.
Please have a look at my yml file:
version: '2'
services:
data_container:
build: ./data
#volumes:
# - dataVolume:/data
db:
build: ./db
ports:
- "5445:5432"
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
# - PGDATA=/var/lib/postgresql/data/pgdata
volumes_from:
# - container:db_bus
- data_container
geoserver:
build: ./geoserver
depends_on:
- db
ports:
- "8004:8080"
volumes:
- ./geoserver/data:/opt/geoserverdata_dir
web:
build: ./web
volumes:
- ./web:/code
ports:
- "8000:8000"
depends_on:
- db
command: python manage.py runserver 0.0.0.0:8000
nginx:
build: ./nginx
ports:
- "83:80"
depends_on:
- web
The Docker file for the data_container is:
FROM stackbrew/busybox:latest
MAINTAINER Tom Offermann <tom#offermann.us>
# Create data directory
RUN mkdir /data
# Create /data volume
VOLUME /data
I tried this but by doing docker-compose down, the data is lost. I tried naming the data_container as you can see the commented line, it threw me this error:
ERROR: Named volume "dataVolume:/data:rw" is used in service "data_container" but no declaration was found in the volumes section.
So right now what I am doing is I created a stand alone data only named container and put that in the volumes_from value of the db. It worked fine and didn't remove any data even after doing docker-compose down.
My queries:
What is the best approach to make containers that can store database's data using the docker-compose and to use them properly ?
My conscious is not agreeing with me on approach that I have opted, the one by creating a stand alone data container. Any thoughts?
docker-compose down
does the following
Stops containers and removes containers, networks, volumes, and images
created by up
So the behaviour you are experiencing is expected.
Use docker-compose stop to shutdown containers created with the docker-compose file but not remove their volumes.
Secondly you don't need the data-container pattern in version 2 of docker compose. So remove that and just use
db:
...
volumes:
- /var/lib/postgresql/data
docker-compose down stops containers but also removes them (with everything: networks, ...).
Use docker-compose stop instead.
I think the best approach to make containers that can store database's data with docker-compose is to use named volumes:
version: '2'
services:
db: #https://hub.docker.com/_/mysql/
image: mysql
volumes:
- "wp-db:/var/lib/mysql:rw"
env_file:
- "./conf/db/mysql.env"
volumes:
wp-db: {}
Here, it will create a named volume called "wp-db" (if it doesn't exist) and mount it in /var/lib/mysql (in read-write mode, the default). This is where the database stores its data (for the mysql image).
If the named volume already exists, it will be used without creating it.
When starting, the mysql image look if there are databases in /var/lib/mysql (your volume) in order to use them.
You can have more information with the docker-compose file reference here:
https://docs.docker.com/compose/compose-file/#/volumes-volume-driver
To store database data make sure your docker-compose.yml will look like
if you want to use Dockerfile
version: '3.1'
services:
php:
build:
context: .
dockerfile: Dockerfile
ports:
- 80:80
volumes:
- ./src:/var/www/html/
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- mysql-data:/var/lib/mysql
adminer:
image: adminer
restart: always
ports:
- 8080:8080
volumes:
mysql-data:
your docker-compose.yml will looks like
if you want to use your image instead of Dockerfile
version: '3.1'
services:
php:
image: php:7.4-apache
ports:
- 80:80
volumes:
- ./src:/var/www/html/
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- mysql-data:/var/lib/mysql
adminer:
image: adminer
restart: always
ports:
- 8080:8080
volumes:
if you want to store or preserve data of mysql then
must remember to add two lines in your docker-compose.yml
volumes:
- mysql-data:/var/lib/mysql
and
volumes:
mysql-data:
after that use this command
docker-compose up -d
now your data will persistent and will not be deleted even after using this command
docker-compose down
extra:- but if you want to delete all data then you will use
docker-compose down -v
to verify or check database data list by using this command
docker volume ls
DRIVER VOLUME NAME
local 35c819179d883cf8a4355ae2ce391844fcaa534cb71dc9a3fd5c6a4ed862b0d4
local 133db2cc48919575fc35457d104cb126b1e7eb3792b8e69249c1cfd20826aac4
local 483d7b8fe09d9e96b483295c6e7e4a9d58443b2321e0862818159ba8cf0e1d39
local 725aa19ad0e864688788576c5f46e1f62dfc8cdf154f243d68fa186da04bc5ec
local de265ce8fc271fc0ae49850650f9d3bf0492b6f58162698c26fce35694e6231c
local phphelloworld_mysql-data