Dockerfile - deploy mysql dump in entrypoint - mysql

Is it possible to connect to external container in entrypoint and upload DB dump to it?
I always get web_1 exited with code 0 on this line execution: mysql -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < magento-sample-data-1.9.1.0/magento_sample_data_for_1.9.1.0.sql in install-sampledata from Dockerfile
However, I can do docker exec -it <> bash after containers creation, execute install-sampledata there and it works
I have such docker-compose
version: '2.1'
services:
db:
image: mysql:5.6.23
volumes:
- db-data:/var/lib/mysql/data
env_file:
- env
web:
build: .
ports:
- "8089:80"
links:
- db
env_file:
- env
tty: true
volumes:
db-data:
Dockerfile
FROM alexcheng/magento
ENTRYPOINT install-sampledata
and install-sampledata file
#!/usr/bin/env bash
cd /tmp
cp /opt/magento-sample-data-1.9.1.0.tgz .
tar xvf magento-sample-data-1.9.1.0.tgz
cp -R magento-sample-data-1.9.1.0/media/* /var/www/htdocs/media/
cp -R magento-sample-data-1.9.1.0/skin/* /var/www/htdocs/skin/
chown -R www-data:www-data /var/www/htdocs/media
mysql -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < magento-sample-data-1.9.1.0/magento_sample_data_for_1.9.1.0.sql

The problem is: your ENTRYPOINT is install-sampledata: a script which will run one mysql command and... exit!
At this point the container will stop.
If possible, it is best to call that script, and then call mysql as in the mysql Dockerfile, in order to leave a foreground process running.
Or you can have a look at multi-stage build, in order to build an image with your pre-requisite files already baked in.

You have an entry point in mysql containers that allows you to have the container use your mysql dump upon startup. Make a volume to here /docker-entrypoint-initdb.d and you're container will populate your database.

Add
sh -c /bin/bash
at last to your install-sampledata script. It will start a new process bash with a new pid. So your container will not die.

Related

How to install nc in mysql container

I am getting this message
nc command is missing and by doing some R&D, I got to know that in order to resolve this, (I think) I need to run below command in MySQL container in docker-compose
RUN apt-get -q update && apt-get -qy install netcat
But the issue is I don't have it's docker file else I could have written this command in docker file and might have called docker file from docker-compose
Does anyone have any idea how can I run this command from docker-compose?
Edit 1:
I have made separate the DockerFile for mysql which consists of
FROM mysql:8
RUN apt-get -q update && apt-get -qy install netcat
COPY wait-for.sh .
and then called this docker file from docker-compose which goes like this...
version: "3"
services:
mysql-standalone:
image: mysql:8.0.25
environment:
- MYSQL_ROOT_PASSWORD=********
- MYSQL_DATABASE=usermanagementappdp
ports:
- 3306:3306
depends_on: ['eureka-server']
build:
context: "./mysqlDockerFile2"
dockerfile: "Dockerfile"
volumes:
- ./wait-for:/docker-entrypoint-initdb.d
entrypoint: ["/docker-entrypoint-initdb.d/wait-for.sh", "eureka-server:8761", "--", "docker-entrypoint.sh"]
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
restart: always
environment:
PMA_HOST: mysql-standalone
PMA_USER: root
PMA_PASSWORD: root123M.
ports:
- 8085:80
eureka-server:
image: eureka-server
ports:
- 8761:8761
build:
context: "../Eureka-Server-For-User-Management-App"
dockerfile: "Dockerfile"
usermanagementapp-docker:
image: usermanagementapp-docker:latest
ports:
- 8089:8089
links:
- eureka-server
environment:
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka-server:8761/eureka
SPRING_DATASOURCE_URL: jdbc:mysql://mysql-standalone:3306/usermanagementappdp?allowPublicKeyRetrieval=true&autoReconnect=true&useSSL=false
build:
context: "./"
dockerfile: "Dockerfile"
restart: on-failure
entrypoint: ["/wait-for.sh", "mysql-standalone:3306", "--", "['java','-jar','/app.jar']"]
depends_on: ['mysql-standalone','eureka-server']
Docker file for User management app is:
FROM openjdk:8
Add target/User-Management-App-0.0.1-SNAPSHOT.jar app.jar
VOLUME /tmp
EXPOSE 8089
RUN apt-get -q update && apt-get -qy install netcat
COPY wait-for.sh .
COPY target/User-Management-App-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Docker file for Eureka- server
FROM openjdk:8
EXPOSE 8761
ADD /target/Eureka-Server-For-User-Management-App-0.0.1-SNAPSHOT.jar netflix-eureka-server-1.0.jar
COPY wait-for.sh .
netflix-eureka-server-1.0.jar
ENTRYPOINT ["java","-jar","netflix-eureka-server-1.0.jar"]
Edit 2
I just edited mysql docker file to check if it is even getting executed or not
RUN echo "'Entered in docker file of mysql'"
FROM mysql:8
RUN apt-get -q update && apt-get -qy install netcat
COPY wait-for.sh .
RUN echo "'Exiting docker file of mysql'"
and found that on doing docker-compose up it is not echoing the text
You don't need to install netcat in the database server container. There are a couple of other things you can clean up to simplify this setup.
Let's start by thinking through what needs to happen when you run docker-compose up. The application container can't function until the database is up and running; for that, the application container is using the wait-for script, which in turn uses nc. The database itself doesn't need to make any outbound connections, though; it needs to start up and accept inbound connections so the rest of the system can proceed. So you don't need nc in the database server container, and you can just use the standard unmodified mysql image.
(In your Dockerfile you show the database depending on the Eureka service registry; but the database itself won't do anything to connect to it, and you're using a direct connection to the database from your application. It doesn't need to be part of this stack.)
Your Compose setup also overrides the image's entrypoint:. This shouldn't usually be necessary. I'd suggest a pattern where the image's ENTRYPOINT is a self-contained script that ends with a shell exec "$#" command, which will let it run the CMD passed to it as arguments. So that script could look something like
#!/bin/sh
# ./entrypoint.sh
# Set defaults for common environment variables
: ${MYSQL_PORT:=3306}
: ${MYSQL_DATABASE:=usermanagementappdp}
# Wait for the database to be ready
./wait-for.sh "$MYSQL_HOST:$MYSQL_PORT"
# Dynamically set the Spring database URL
export SPRING_DATASOURCE_URL="jdbc:mysql://$MYSQL_HOST:$MYSQL_PORT/$MYSQL_DATABASE?allowPublicKeyRetrieval=true&autoReconnect=true&useSSL=false"
# Run the main container command
exec "$#"
Then in your application's Dockerfile -- again, you don't need to change anything in the database's Dockerfile -- set this script as the ENTRYPOINT, and make your java -jar command the CMD.
FROM openjdk:8
# Install OS-level dependencies before COPYing anything in
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install --no-install-recommends --assume-yes \
netcat
# COPY in the actual application (don't usually ADD things)
WORKDIR /app
COPY target/User-Management-App-0.0.1-SNAPSHOT.jar app.jar
COPY wait-for.sh entrypoint.sh .
# Set metadata for how to run the application
EXPOSE 8089
ENTRYPOINT ["./entrypoint.sh"] # must be JSON-array syntax
CMD ["java", "-jar", "app.jar"]
Now in your docker-compose.yml setup you can get rid of most of the overrides. Run an unmodified mysql image and don't override the command: or entrypoint: of anything.
version: "3.8"
services:
mysql-standalone:
image: mysql:8.0.25
environment:
- MYSQL_ROOT_PASSWORD=********
- MYSQL_DATABASE=usermanagementappdp
ports:
- 3306:3306
phpmyadmin: { image: phpmyadmin/phpmyadmin, ... }
eureka-server:
build: ../Eureka-Server-For-User-Management-App
usermanagementapp-docker:
ports:
- 8089:8089
environment:
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://eureka-server:8761/eureka
MYSQL_HOST: mysql-standalone
build: .
restart: on-failure
depends_on: [mysql-standalone, eureka-server]
The setup you show above will contaminate your local copy of the MySQL image, so before you start, you should clean it up
docker pull mysql:8.0.25
If you need to do some sort of registration in the MySQL image at startup time, then you can follow this same basic approach. It is helpful to look up the Docker Hub mysql image page and from there its Dockerfile because you will need to know the original ENTRYPOINT and CMD.
In the ENTRYPOINT wrapper script, at the end, run the original entrypoint:
#!/bin/sh
# my-entrypoint.sh
...
exec docker-entrypoint.sh "$#" # running the original entrypoint
In your derived Dockerfile, you'll need to repeat the original CMD
FROM mysql:8.0.27
...
COPY wait-for.sh my-entrypoint.sh /usr/local/bin
ENTRYPOINT ["my-entrypoint.sh"]
CMD ["mysqld"]
In your Compose file, do not specify both image: mysql and a build: block. This will overwrite your local copy of the Docker Hub image with your custom build. For most purposes you can only specify build: and ignore image:. You do not need to use volumes: to inject code, that's contained within the custom Dockerfile.
services:
mysql-standalone:
build: ./mysql
# no image:
You could build and publish your own container image if you wanted with a dockerfile like this
FROM mysql:8
RUN apt-get -q update && apt-get -qy install netcat
and build it like docker build . -t user123/mysql:8
and push it like docker push user123/mysql:8
then switch your docker compose to use your custom container.
if you just need to pop in temporarily to install netcat, you can do that by doing
docker exec -it --user=root ContainerHashOrName /bin/bash where ContainerHashOrName can be retrieved from docker ps then just run your commands like you would on any other distro. Just be aware that you are only making changes to the specific instance of a container and that any rescheduling will bring up a different instance of the container.
You can use "build" option of compose file, https://docs.docker.com/compose/compose-file/compose-file-v3/#build and use your own Dockerfile starts with FROM mysql:8 and then install all additional stuff you need.

docker-entrypoint-initdb.d is empty when container is started from within another container

I have a directory structure like -
- Dockerfile
- docker-compose.yml
- db
- schema.sql
and contents of each file is -
Dockerfile -
FROM alpine:3.7
RUN apk update && \
apk add --no-cache docker python3 && \
apk add --no-cache --virtual .docker-compose-deps python3-dev libffi-dev openssl-dev gcc libc-dev make && \
pip3 install docker-compose && \
apk del .docker-compose-deps
ADD . .
docker-compose.yml -
version: "2"
services:
test_mysql:
image: "mysql:5.7"
container_name: test_mysql_v1
volumes:
- ./db:/docker-entrypoint-initdb.d/
environment:
- MYSQL_ROOT_PASSWORD=root
ports:
- "3310:3306"
schema.sql -
create database if not exists db2;
When I do -
docker-compose up --build --remove-orphans
it behaves expectedly and I get a db called db2 inside test_mysql_v1 container.
However, when I do -
1. docker build -t dfd_1 .
2. docker run -v /var/run/docker.sock:/var/run/docker.sock -it dfd_1 sh
from inside -
3. docker-compose up --build --remove-orphans
Then in newly created test_mysql_v1 container, docker-entrypoint-initdb.d directory is empty (no db created).
Can someone please help how to make this work?
End result should be - when I run docker-compose up from inside dfd_1 container, it should create a mysql container with db already created.
Additional notes -
To bring down mysql container, I use - docker-compose down
My guess is when I do docker run -v /var/run/docker.sock:/var/run/docker.sock ..., then I require another volume mount so that docker-compose.yml (inside dfd_1) can copy db to docker-entrypoint-initdb.d correctly.
Got nothing from docker logs.
Any help is appreciated. Thanks.
Achieved it by passing path on host directory to the container within.
Changed docker run command as -
docker run -v /var/run/docker.sock:/var/run/docker.sock -e HOST_DIR=$PWD -it dfd_1 sh
And docker-compose.yml (used HOST_DIR env variable while mapping volume) as -
version: "2"
services:
test_mysql:
image: "mysql:5.7"
container_name: test_mysql_v1
volumes:
- ${HOST_DIR}/db:/docker-entrypoint-initdb.d/
environment:
- MYSQL_ROOT_PASSWORD=root
ports:
- "3310:3306"

How to launch a service like mysql in a docker container?

So I've tried to create a docker-compose.yml file to create one container for my web app with laravel and an other container for my database with mariadb. I've tried to link those two container together so that laravel could fetch data from mariadb. The problem is that my laravel container does not have a mysql socket file, so it can't use mysql. I'm pretty sure that I've missed something, or that I don't understood something because nothing works. So my question is how do we propely connect a archlinux container with laravel to a mysql container? Here's my docker-compose file
version: '3'
services:
database:
build: ./database
container_name: database.dev
command: mysqld --user=root --verbose
ports:
- "3307:3306"
restart: always
web:
build: .
volumes:
- "/app"
ports:
- "8000:8000"
links:
- database
depends_on:
- database
When I'm trying to install mysql in my archlinux container, mysql won't create a service at /etc/init.d/mysql or event a socket file at /run/mysqld/mysqld.sock. I get this output when I try to use mysql in my container terminal.
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/run/mysqld/mysqld.sock' (2 "No such file or directory")
Here are my docker files:
database/Dockerfile
FROM mysql:latest
RUN mkdir -p /db
WORKDIR /db
COPY . /db
RUN cd /db
RUN /etc/init.d/mysql start
Dockerfile
FROM base/archlinux
RUN mkdir -p /app
WORKDIR /app
COPY . /app
RUN pacman -Syu --noconfirm
RUN pacman -S openssh composer php mariadb --noconfirm
RUN groupadd -g 89 mysql &>/dev/null
RUN useradd -u 89 -g mysql -d /var/lib/mysql -s /bin/false mysql &>/dev/null
#RUN chown -R mysql:mysql var/lib/mysql &>/dev/null
RUN mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
RUN COMPOSER_ALLOW_SUPERUSER=1
RUN cd /app
RUN /usr/bin/composer install
RUN echo APP_KEY= > .env
RUN echo DB_USERNAME=root >> .env
RUN echo DB_PASSWORD= >> .env
RUN cat php.ini > /etc/php/php.ini #my custom configuration for the project
RUN php artisan key:generate
RUN ln -srf storage/app/public public/storage
RUN php artisan storage:link
VOLUME ["/app"]
EXPOSE 8000
CMD php /app/artisan serve --host=0.0.0.0 --port=8000
I don't feel like I'm doing the proper thing, anyone can help me or show me the right way?
This repository on GitHub is an ArchLinux based image for docker, it includes PHP, PHP-composer, MySQL, PostgreSQL, and MariaDB. I just had to tweak it a bit to make it work and suits my needs!

Import data.sql MySQL Docker Container

If I have a data.sql, how I can import database to my mysql docker container? How I can import database data. In a dockerised world this adds a layer of complexity. some methods please.
Here my docker-compose.yml:
nginx:
build: ./nginx/
container_name: nginx-container
ports:
- 80:80
links:
- php
volumes_from:
- app-data
php:
build: ./php/
container_name: php-container
expose:
- 9000
links:
- mysql
volumes_from:
- app-data
app-data:
image: php:7.0-fpm
container_name: app-data-container
volumes:
- ./www/html/:/var/www/html/
command: "true"
mysql:
image: mysql:latest
container_name: mysql-container
ports:
- 3306:3306
volumes_from:
- mysql-data
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: name_db
MYSQL_USER: user
MYSQL_PASSWORD: password
mysql-data:
image: mysql:latest
container_name: mysql-data-container
volumes:
- /var/lib/mysql
command: "true"
You can import database afterwards:
docker exec -i mysql-container mysql -uuser -ppassword name_db < data.sql
Mount your sql-dump under/docker-entrypoint-initdb.d/yourdump.sql utilizing a volume mount
mysql:
image: mysql:latest
container_name: mysql-container
ports:
- 3306:3306
volumes:
- ./dump.sql:/docker-entrypoint-initdb.d/dump.sql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: name_db
MYSQL_USER: user
MYSQL_PASSWORD: password
This will trigger an import of the sql-dump during the start of the container, see
https://hub.docker.com/_/mysql/ under "Initializing a fresh instance"
I can't seem to make this work with the latest mysql or mysql:5.7. So I use mariaDB instead. Here is my docker-compose.yaml code.
version: '3'
services:
mysql:
image: mariadb:10.3
container_name: mariadb
volumes:
- container-volume:/var/lib/mysql
- ./dump.sql:/docker-entrypoint-initdb.d/dump.sql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: name_db
ports:
- "3306:3306"
volumes:
container-volume:
Another option if you don't wanna mount a volume, but wanna dump a file from your local machine, is to pipe cat yourdump.sql. Like so:
cat dump.sql | docker exec -i mysql-container mysql -uuser -ppassword db_name
See:
https://gist.github.com/spalladino/6d981f7b33f6e0afe6bb
Just write docker ps and get the container id and then write the following;
docker exec -i your_container_id mysql -u root -p123456 your_db_name < /Users/your_pc/your_project_folder/backup.sql
Import using docker-compose
cat dump.sql | docker-compose exec -T <mysql_container> mysql -u <db-username> -p<db-password> <db-name>
combine https://stackoverflow.com/a/51837876/1078784
and answers in this question, I think the best answer is:
cat {SQL FILE NAME} | docker exec -i {MYSQL CONTAINER NAME} {MYSQL PATH IN CONTAINER} --init-command="SET autocommit=0;"
for example in my system this command should look like:
cat temp.sql | docker exec -i mysql.master /bin/mysql --init-command="SET autocommit=0;"
also you can use pv to moniter progress:
cat temp.sql | pv | docker exec -i mysql.master /bin/mysql --init-command="SET autocommit=0;"
And the most important thing here is "--init-command" which will speed up the import progress 10 times fast.
I can import with this command
docker-compose exec -T mysql mysql -uroot -proot mydatabase < ~/Desktop/mydatabase_2019-10-05.sql
you can follow these simple steps:
FIRST WAY :
first copy the SQL dump file from your local directory to the mysql container. use docker cp command
docker cp [SRC-Local path to sql file] [container-name or container-id]:[DEST-path to copy to]
docker cp ./data.sql mysql-container:/home
and then execute the mysql-container using (NOTE: in case you are using alpine version you need to replace bash with sh in the given below command.)
docker exec -it -u root mysql-container bash
and then you can simply import this SQL dump file.
mysql [DB_NAME] < [SQL dump file path]
mysql movie_db < /home/data.sql
SECOND WAY : SIMPLE
docker cp ./data.sql mysql-container:/docker-entrypoint-initdb.d/
As mentioned in the mysql Docker hub official page.
Whenever a container starts for the first time, a new database is created with the specified name in MYSQL_DATABASE variable - which you can pass by setting up the environment variable see here how to set environment variables
By default container will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d folder. Files will be executed in alphabetical order. this way your SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.
for more details you can always visit the official page
do docker cp file.sql <CONTAINER NAME>:/file.sql first
then docker exec -it <CONTAINER NAME> mysql -u user -p
then inside mysql container execute source \file.sql
Trying "docker exec ... < data.sql" in Window PowerShell responses with:
The '<' operator is reserved for future use.
But one can wrap it out with cmd /c to eliminate the issue:
cmd /c "docker exec -i mysql-container mysql -uuser -ppassword name_db < data.sql"
This one work for me
$ docker exec -i NAME_CONTAINER_MYSQL mysql -u DB_USER -pPASSWORD DATABASE < /path/to/your/file.sql
First if do you want to know what is the NAME_CONTAINER_MYSQL, you should use
this command below :
$ docker ps
In the output column NAME you will see the NAME_CONTAINER_MYSQL that do you need to replace in the command above.
You can run a container setting a shared directory (-v volume), and then run bash in that container. After this, you can interactively use mysql-client to execute the .sql file, from inside the container. obs: /my-host-dir/shared-dir is the .sql location in the host system.
docker run --detach --name=test-mysql -p host-port:container-port --env="MYSQL_ROOT_PASSWORD=my-root-pswd" -v /my-host-dir/shared-dir:/container-dir mysql:latest
docker exec -it test-mysql bash
Inside the container...
mysql -p < /container-dir/file.sql
Custom parameters:
test-mysql (container name)
host-port and container-port
my-root-pswd (mysql root password)
/my-host-dir/shared-dir and /container-dir (the host directory that will be mounted in the container, and the container location of the shared directory)
you can copy the export file for e.g dump.sql using docker cp into the container and then import the db. if you need full instructions, let me know and I will provide

mkdir error: Cannot create directory '' - when trying to start mysql container with docker-compose up

I'm having a baffling time with docker-compose and mysql. When I try to start my mysql container with docker-compose, I get an uninformative mkdir error. My Dockerfile and docker-compose.yml don't even seem to contain a mkdir command for mysql.
Here is configuration:
docker-compose.yml
db:
build: docker/mysql
volumes:
- ./database:/var/lib/mysql
environment:
- MYSQL_DATABASE=xxxx
- MYSQL_USER=xxxx
- MYSQL_PASSWORD=xxxx
- MYSQL_ROOT_PASSWORD=xxxx
privileged: true
hostname: "docker.mysql"
Dockerfile
FROM mysql:5.6
MAINTAINER "ABC" <developers#abc.com>
ADD my.cnf /etc/mysql/my.cnf
RUN usermod -u 1000 mysql
RUN usermod -G staff mysql
RUN chown mysql /var/run/mysqld
EXPOSE 3306
my.cnf pastebin
http://pastebin.com/iVSGxhGV
sudo docker --version
Docker version 1.10.0, build 590d5108
This is a docker setup built by my team mates, so I am not sure what the priviledged:true line is doing, but when I remove it, everything appears to work.
with privileged:true
sudo docker-compose up db
Creating appname_db_1
Attaching to appname_db_1
db_1 | mkdir: cannot create directory '': No such file or directory
appname_db_1 exited with code 1
Once privileged: true is removed, it seems to work.
Does anyone know why this might be?