Reference Dockerfile from docker-compose.yml? - docker

I have a web service that uses a MySQL as its backing store. I want to Dockerize this service as well as its MySQL DB. For the service I have the following Dockerfile:
FROM openjdk:8-jdk-alpine as cce
COPY build/libs/my-service.jar my-service.jar
EXPOSE 9200
ENTRYPOINT [ \
"java", \
"-Ddb.hostAndPort=my-service-db:3306", \
"-Ddb.name=my_service_db_local", \
"-Ddb.username=my-service-user", \
"-Ddb.password=abc123", \
"-jar", \
"my-service.jar" \
]
If I understand the Docker ecosystem correctly, it sounds like I can write a Docker Compose file to spin up the MySQL container instance as well as the web service container instance. So I have a docker-compose.yml file started that looks like so:
version: "3.7"
services:
my-service-db:
image: mysql:8
container_name: my-service-db
command: --default-authentication-plugin=mysql_native_password
restart: always
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: r00tdud3
MYSQL_DATABASE: my_service_db_local
MYSQL_USER: my-service-user
MYSQL_PASSWORD: abc123
volumes:
- ./my-service-db-data:/var/lib/mysql
my-service:
??? how to specify local Dockerfile here ???
depends_on:
- my-service-db
From my own tinkering I'm confident the MySQL container is configured the way I want it and correctly. Now I'm just trying to figure out how to tell docker-compose.yml file (which will live in the root directory of my project, right alongside the Dockerfile) to use the service's Dockerfile, and that it depends on the MySQL container first being started/running. I think I'm close but I'm having a hard time crossing the finish line.
Can anyone help me configure docker-compose.yml to create a service called my-service that uses the local Dockerfile for its config?

You can create an image from the dockerfile:
docker build - < Dockerfile
Then you should tag you image with a proper name.
After creating the image reference it in the docker-compose.yml file:
my-service:
image: ${image_name}
Another option is to simply write:
my-service:
build: .

Related

Not able to mount Docker Volume for PhpMyAdmin

I've install MySQL and PhpMyAdmin on docker
MySQL volume mount works perfectly fine,
But I also want container's /var/www/html/libraries, /var/www/html/themes folders to be saved/persisted to my host.
So that If I change any file and it stays like that..
This is my docker-compose.yml
version: '3.5'
services:
mysql:
container_name: mysql
image: mysql
restart: always
volumes:
- ./var/lib/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
phpmyadmin:
container_name: phpmyadmin
image: phpmyadmin/phpmyadmin:latest
restart: always
volumes:
- ./phpmyadmin/libraries:/var/www/html/libraries # Here's the problem
- ./phpmyadmin/themes:/var/www/html/themes # Here's the problem
environment:
PMA_HOST: mysql
The current problem is,
it does create the folders /phpmyadmin/libraries, /phpmyadmin/themes
But inside they're empty and the container's directories (/var/www/html/libraries, /var/www/html/themes) also becomes empty.
I'm very new to Docker, and currently I've no clue :(
Many Thanks in advance.
Your problem is that /var/www/html is populated at build time and volumes are mounted at run time which causes /var/www/html to be overwritten by what you have locally (i.e. nothing).
You need to extend the Dockerfile for PHPMyAdmin to delay populating those directories until after the volumes have been mounted. You'll need something like this setup:
Modify docker-compose.yml to the following:
...
phpmyadmin:
container_name: phpmyadmin
build:
# Use the Dockerfile located at ./build/phpmyadmin/Dockerfile to build this image
context: ./build/phpmyadmin
dockerfile: Dockerfile
restart: always
volumes:
- ./phpmyadmin/libraries:/var/www/html/libraries
- ./phpmyadmin/themes:/var/www/html/themes
environment:
PMA_HOST: mysql
Create a file at ./build/phpmyadmin/Dockerfile with this content:
FROM phpmyadmin/phpmyadmin:latest
# Move the directories you want into a temporary directory
RUN mv /var/www/html /tmp/
# Modify the start up of this image to use a custom script
COPY ./custom-entrypoint.sh /custom-entrypoint.sh
RUN chmod +x /custom-entrypoint.sh
ENTRYPOINT ["/custom-entrypoint.sh"]
CMD ["apache2-foreground"]
Create a custom entrypoint at ./build/phpmyadmin/custom-entrypoint.sh with this content:
#!/bin/sh
# Copy over the saved files
cp -r /tmp/html /var/www
# Kick off the original entrypoint
exec /docker-entrypoint.sh "$#"
Then you can build and start everything with docker-compose up --build.
Note: this will probably cause issues for you if you're trying to version control these directories - you'll probably need to modify custom-entrypoint.sh.

Docker Drupal 8: ERROR: Cannot locate specified Dockerfile: Dockerfile

I already followed different stackoverflow post, but still getting this issue. I am running Drupal 8 and moving project to Docker.
So on root I have created docker-compose.yml I have created file & below is my content
version: '3'
services:
mysql:
image: mysql:5.7
container_name: drupal-mysql
environment:
MYSQL_DATABASE: drupal
MYSQL_USER: root
MYSQL_PASSWORD: root
volumes:
- db_data:/var/lib/mysql:delegated
restart: always
drupal:
image: drupal:latest
container_name: drupal
depends_on:
- mysql
build: .
ports:
- "8080:80"
volumes:
- ./drupal:/drupal
restart: always
volumes:
db_data:
While running docker-compose up -d --build it gives
Building drupal
ERROR: Cannot locate specified Dockerfile: Dockerfile
In the definition of the drupal service build: . is telling docker compose that the relative Dockerfile should be in the same directory where docker-compose.yml is.
Make sure the path is correct or change it accordingly, the path is relative to the docker file location.
Please, check the compose file build and context sections for further details.
You need to remove build command (which is after depends_on) from your drupal service section of docker-compose file.
Since you are already providing image, you need not build it. So you can just run docker-compose up without --build arg.
If you need to build 'drupal' service then you need to provide build information with (buildContext as current directory in most cases and dockerfile).

Wait for a docker container to be ready with command in docker-compose.yml

I have a mysql-db and prisma image in my docker-compose.yml. I want prisma to wait for the db to be ready, cause otherwise prisma keeps restarting and it wont work at all. And I know from here, that I can use ./wait-for-it but I was not able to connect the pieces after searching for a while.
version: '3'
services:
prisma:
image: prismagraphql/prisma:1.25
restart: unless-stopped
ports:
- "4001:4466"
depends_on:
- db
# I added this command
command: ["./wait-for-it.sh", "db:33061", "--"]
environment:
PRISMA_CONFIG: |
managementApiSecret: server.secret.123
port: 4466
databases:
default:
connector: mysql
active: true
host: db
port: 3306
user: ***
password: ***
db:
image: mysql:5.7
restart: unless-stopped
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_USER: ***
MYSQL_ROOT_PASSWORD: ***
ports:
- "33061:3306"
volumes:
- /docker/mysql:/var/lib/mysql
I added the command above but nothing changed, not even an error in the logs but as I understand, the command is run inside the container.
How do I get the ./wait-for-it.sh into the container?
And can this even work this way with the command or does this depend
on the prisma-image?
Otherwise, how would I achieve the waiting?
I just have the docker-compose file and want to do docker-compose up -d
Now I found out how to include wait-for-it.sh into the container.
I downloaded the wait-for-it.sh into the project folder and then I created a file called Dockerfile with the contents:
FROM prismagraphql/prisma:1.25
COPY ./wait-for-it.sh /app/wait-for-it.sh
RUN chmod +x /app/wait-for-it.sh
ENTRYPOINT ["/bin/sh","-c","/app/wait-for-it.sh db:3306 -t 30 -- /app/start.sh"]
In my docker-compose.yml I replaced
image: prismagraphql/prisma:1.25 with build: . which causes a new build from the Dockerfile in my project path.
Now the new image will be built from the prisma image and the wait-for-it.sh will be copied into the new image. Then the ENTRYPOINT is overridden and prisma will wait until the db is ready.
You are confusing internal and external ports. Database is visible on port 3306 inside your network, so you have to wait on db:3306 and not on 33061.
Port exposing has no effect inside user-defined bridge network, created by default by docker-compose. All ports are visible to containers inside network by default. When you expose port, you make it visible outside network.
Also, make sure what is ENTRYPOINT for image prismagraphql/prisma:1.25. If it is not /bin/sh -c or other type of shell, your command wont get executed.
UPD
If you get ENTRYPOINT in base image different from /bin/sh -c, you can override it. Supposing you have /bin/sh -c /app/start.sh, you could do following magic:
docker-compose.yml
...
services:
prisma:
entrypoint: ["/bin/sh", "-c", "'./wait-for-it.sh db:3306 && /app/start.sh'"]

Storing MySQL data in an image file (formatted as ext4)

I'm trying to use Docker to containerize a MySQL (MariaDB actually) database. I figured out how to store MySQL data (/var/lib/mysql) in a volume mounted from a host directory.
However, because the underlying filesystem is different from host to host there are some inconsistencies, for example table names are case insensitive on NTFS (Windows). Also, it looks like if the database is created on a Linux host it doesn't work on a Windows host (haven't figured out why exactly).
Therefore, I want to store the data on a disk image and mount it inside the container, i.e. db-data.img formatted as ext4. But I'm facing a strange problem, when mounting this image inside the container:
$ docker run -v $PWD:/outside --rm -it ubuntu /bin/bash
# dd if=/dev/zero of=/test.img bs=1M count=100
# mkfs.ext4 test.img
# mount -o loop -t ext4 test.img /mnt
mount: /mnt: mount failed: Operation not permitted.
Using another directory instead of /mnt didn't work either.
Why does it refuse to mount the img file?
I would suggest to use docker-compose and just use a volume declared in the docker-compose.yml configuration.
Something like this:
version: '3'
services:
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
MYSQL_USER: $MYSQL_USER
MYSQL_PASS: $MYSQL_PASSWORD
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
The mysql-data volume should be stored as a separate volume, independent from the host operating system. The difference to just mounting a directory on the host, it's basically mounting a volume container (which you could also do without docker-compose, but it's more work).
It will not work inside of docker image, Docker blocks access to mouning filesystems (and loop devices). Should be easier create these image earlier, mount and connect to docker as folder by -v.
P.S. Another option is dump your database to sql and restore from windows.
I managed to solve this by using the privileged option in docker-compose.yml:
privileged: true
(or --privileged in the docker command)
Here is my final docker-compose.yml:
version: '3'
services:
db:
build: ./db
image: my_db
container_name: db
privileged: true
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
volumes:
- ${MYSQL_DATA_IMG}:/data.img
restart: always
Dockerfile:
FROM mariadb
COPY my-custom.cnf /etc/mysql/conf.d/custom.cnf
COPY run.sh /usr/local/bin/run-mariadb.sh
ENTRYPOINT ["run-mariadb.sh"]
and a custom entry point script that executes mount (run.sh):
#!/bin/sh
# For this mount comamnd to work the DB container must be started
# with --privileged.
mount -o loop /data.img /var/lib/mysql
# Call the entry point script of MariaDB image.
exec /usr/local/bin/docker-entrypoint.sh mysqld
for storing database data make 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
plus you can check your data list by this command
docker volume ls
DRIVER VOLUME NAME
local 35c819179d883cf8a4355ae2ce391844fcaa534cb71dc9a3fd5c6a4ed862b0d4
local 133db2cc48919575fc35457d104cb126b1e7eb3792b8e69249c1cfd20826aac4
local 483d7b8fe09d9e96b483295c6e7e4a9d58443b2321e0862818159ba8cf0e1d39
local 725aa19ad0e864688788576c5f46e1f62dfc8cdf154f243d68fa186da04bc5ec
local de265ce8fc271fc0ae49850650f9d3bf0492b6f58162698c26fce35694e6231c
local phphelloworld_mysql-data

Docker container exited with code 0 after docker-compose up -d

I know the question has been asked in various situations, but I'm still stucked despite everything I read on the Internet.
I want to have a script executed after the container "mywebsite" is built and I used ENTRYPOINT for that and I know that in normal use, after the ENTRYPOINT command is executed, the container "mywebsite" exit. I tried several tricks to avoid exit, unfortunately without success.
In my DOCKERFILE I have this :
FROM php:7.1.17-apache
[...]
WORKDIR /var/www
COPY docker-entrypoint.sh /var/www/docker-entrypoint.sh
ENTRYPOINT ["sh", "/var/www/docker-entrypoint.sh"]
Then in my docker-entrypoint.sh I have this :
#!/bin/bash
set -e
cd www
chown -R www-data:www-data sites modules themes
exec "$#"
And here is my docker-compose.yml :
version: '3.3'
services:
mywebsite:
build: .
extra_hosts:
- "mywebsite.local:127.0.0.1"
hostname: mywebsite
domainname: local
ports:
- 8088:80
volumes:
- ./www:/var/www/www
- ./vendor:/var/www/vendor
- ./scripts:/var/www/scripts
links:
- database:database
restart: always
tty: true
database:
image: mysql:5.5.49
container_name: mysql-container
ports:
- 3307:3306
volumes:
- ./www/dumps/mywebsite.sql:/docker-entrypoint-initdb.d/dump.sql
restart: always
command: --max_allowed_packet=32505856
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mywebsite
When build, all steps are fine, and everything is set properly, but the container "mywebsite" keep exiting. (The "database" service is running fine)
I haded tty: true and exec "$#" but none of that works.
You can end with command like tail -f /dev/null
I often use this directly in my docker-compose.yml with command: tail -f /dev/null. And it is easy to see how I keep the container running.
I had the same problem when creating my own image from a postgis-image. The problem was that I added an entrypoint. When I removed the entrypoint, build the image again, docker-compose does start my container and postgis was accepting connections.
dockerfile
FROM postgis/postgis:12-master
COPY organisation.sql
#ENTRYPOINT ["docker-entrypoint.sh"] #This was the problem
In docker-compose I did not need command's or tty.
version: "3.7"
services:
mydb:
image: mydb:latest
container_name: mytest
ports:
- "5432:5432"
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret

Resources