After a MySQL docker compose, SQL script execution doesn't work - mysql

I want to create a MySQL Docker container which execute automatically 4 SQL script, such that I can found my schema and user already ready to use. In order to do this, I put in my folder my-mysql 4 SQL script files and my docker-compose.yml as following
version: '3.6'
services:
mysql:
image: mysql:5.7
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=my_password
ports:
- my-ip_address:my_port
volumes:
- mysql:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d
command:
- --max-allowed-packet=64M
volumes:
mysql: {}
I execute it by sudo docker-compose up, checking no other MySQL container before this. And the MySQL container creates itself correctly, but the script doesn't execute it and I can't find my database. How can I solve the problem?

If you have an shell insight you container, so connect to this container like this docker exec -it mysql bash, wher "mysql" stands for the container name.
Look insight this container, and check, if your scripts are located at the right place, if the filesystem-rights matches and if you call / trigger those scrips correctly.

Related

Dockerfile - Run a init sql file for setting up tables

I am able to run a SQL file as follows:
Setup Dockerfile as:
FROM mysql
ENV MYSQL_DATABASE stock_app
COPY ./sql-scripts/ /docker-entrypoint-initdb.d/
Building the image:
docker build -t db.
Run the following command:
docker run -d -p 3306:3306 --name db -e MYSQL_ROOT_PASSWORD=password db
This is working and able to verify that SQL commands inside the script are executed and the table is created.
What changes should I make so that all three steps are done when I do the following command to bring up all my images?
docker-compose up -d
Instead of manually building the image for db and running the command to execute the SQL file, is there an option to place the run SQL file within Dockerfile? That is to include step 3 mentioned above within Dockerfile.
You probably don't even need the Dockerfile unless you are doing something else that isn't listed above. You should be able to do what you want with a simple docker-compose like this:
version: '3.3'
services:
database:
image: mysql
volumes:
- "./sql-scripts:/docker-entrypoint-initdb.d"
environment:
MYSQL_DATABASE: stock_app
MYSQL_ROOT_PASSWORD: password
ports:
- '3306:3306'
Whenever you update your sql script you would need to recreate the containers with docker-compose up -d --force-recreate. By design the mysql image will run any sql files found in the "/docker-entrypoint-initdb.d" folder so you should not have to manually run those every time you recreate the containers.
The mysql image has the a volume mounted that stores the database. If the folder does not exists, it is created and your scripts are applied.
Instead of trying to write a script that destroys the way the base image is built, just change your base image and make it run scripts every times as it is suggested in this question : docker-compose: reinitializing MySQL db every time

connection laravel with mysql container on docker

On Docker I already have a Laravel container and Container MySQL, how to connect the MySQL container and container Laravel on Docker?
This is what docker-compose was made for!
Check out this tutorial: https://docs.docker.com/compose/wordpress/
It's trying to do something similar: connect wordpress to mysql. The key is that both the docker containers defined in docker-compose.yml share the same network - and you can refer to each container by using their logical name. See how the WORDPRESS_DB_HOST environment variable is set to db:3306 - that will resolve to the IP of the mysql container within the docker network.
Basically, all containers must run in the same network.
# create your network
$ docker network create laravel
# start your container and link it to your network
$ docker run -d --network="laravel" --name="mysql01" mysql:8.0
# after your mysql is up and running, connect your second and third container like this
$ docker run -d --network="laravel" --name="latihananakit_web" yourimage:yourtag
$ docker run -d --network="laravel" --name="latihananakit_app" yourimage:yourtag
I'd recommend to use docker-compose for this scenario, because it makes the whole docker run-thing a lot easier.
See here for reference:
https://docs.docker.com/compose/
https://github.com/bitnami/bitnami-docker-laravel/blob/master/docker-compose.yml
TL;DR:
Create your docker-compose.yml like this (you may change environment-variables or other configuration upon your need):
version: '2'
services:
mariadb:
image: 'bitnami/mariadb:latest'
environment:
- ALLOW_EMPTY_PASSWORD=yes
- MARIADB_USER=my_user
- MARIADB_DATABASE=my_database
- MARIADB_PASSWORD=my_password
myapp:
tty: true
image: bitnami/laravel:5-debian-9
environment:
- DB_HOST=mariadb
- DB_USERNAME=my_user
- DB_DATABASE=my_database
- DB_PASSWORD=my_password
depends_on:
- mariadb
ports:
- 3000:3000
volumes:
- ./:/app
And get everything up and running by executing docker-compose up -d in the same directory.

docker-compose mysql init sql is not executed

I am trying to set up a mysql docker container and execute init sql script. Unfortunately the sql script is not executed. What am I doing wrong?
version: '3.3'
services:
api:
container_name: 'api'
build: './api'
ports:
- target: 8080
published: 8888
protocol: tcp
mode: host
volumes:
- './api:/go/src/app'
depends_on:
- 'mysql'
mysql:
image: 'mysql:latest'
container_name: 'mysql'
volumes:
- ./db_data:/var/lib/mysql:rw
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
restart: always
environment:
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
MYSQL_DATABASE: test
ports:
- '3306:3306'
volumes:
db_data:
I execute file with docker-compose up -d --build
The docker-entrypoint-initdb.d folder will only be run once while the container is created (instantiated) so you actually have to do a docker-compose down -v to re-activate this for the next run.
If you want to be able to add sql files at any moment you can look here at a specialized MySql docker image... http://ivo2u.nl/o4
Update for M1 arch:
Here an almost drop-in replacement in MariaDB: http://ivo2u.nl/V1
Many containerized applications, especially stateful ones, have a way of running init scripts (like the sql scripts here) and they are supposed to run only once.
And since they are stateful, the volumes are a source of truth for the containers on whether to run the init scripts or not on container restart.
Like in your case, deleting the folder used for bind mount or using a new named volume should re-run any init scripts present.
These scripts run when you create the container, not every time you start it.
You can docker-compose up --force-recreate mysql to force those scripts to re-run.
Additionally, if you have a volume like this ./db_data:/var/lib/mysql:rw, then you also need to remove ./db_data before recreating the container.
I'm not a docker expert, but this worked for me.

docker-compose: seeing all the services together from command line

I have the following yml file, the services are created correctly, but when installing wordpress I cannot logon to mysql and I need to understand why.
I'm totally new to docker, I'd need to see all the services together from command line (bash), now I'm running a command like
$ sudo docker exec -ti 4295b34c014a /bin/bash
but I get a login to a specific service, how can I view wordpress and mysql together from cli?
yml file (from here):
version: '3.1'
services:
adminer:
image: adminer
ports:
- '8080:8080'
db:
image: mysql
volumes:
- 'wptut:/var/lib/mysql'
environment:
MYSQL_ROOT_PASSWORD: mysqlpassword
wordpress:
image: wordpress
ports:
- '81:80'
volumes:
wptut: null
I'm not sure what you mean by viewing them together, but in order to check if they are running you can use docker ps and if you want to see the logs after you docker-compose up -d use docker-compose logs -f. You should also make sure in WordPress you are referencing your MySQL database properly. For hostname, you should probably use db instead of localhost
Each service is running in a separate container. If you want log access, docker-compose up should stream logs from all three by default. If you detached from the docker-compose up session I think docker-compose logs -f should also combine log output of all services. docker-compose exec attaches to a running container, you can only do that to one container at a time. At the very least you can run docker-compose exec wordpress or another service name as a convenience over the direct docker command you have above. docker-compose logs -f wordpress also works for a one-off.

How to create database in database docker container?

I'm new in docker, so cant understand - if I want to build container of mysql/postgresql/clickhouse etc - how to create database and schema of database/table? Maybe in Dockerfile or i can do it from docker-compose.yml?
I mean, that I dont know when and where to use CREATE DATABASE; CREATE TABLE ...; queries if I use docker containers of popular databases
You can use both docker and docker-compose. For example with docker compose.
Create a file called docker-compose.yml like:
version: '3'
services:
db:
image: percona:5.7
container_name: whatever_you_want
environment:
- MYSQL_DATABASE=${DATABASE}
- MYSQL_ROOT_PASSWORD=${ROOT_PASSWORD}
- MYSQL_USER=${USER}
- MYSQL_PASSWORD=${PASSWORD}
volumes:
- ./data:/docker-entrypoint-initdb.d
ports:
- "3306:3306"
Additionally you need a file under ./data with whatever SQL commands you want to run and and .env file where you define the environmental variables I used in the docker-compose.yml file above like: ${DATABASE}
Your .env file:
# MySQL
DATABASE=db_name_here
ROOT_USER=root
ROOT_PASSWORD=root
USER=dev
PASSWORD=dev
Your file with SQL commands to execute ./data/init.sql (you can name the file whatever you want)
CREATE DATABASE 'whatever';
DROP DATABASE 'whatever';
-- you can do whatever you want here
This file will be executed each time you do:
docker-compose up -d db
At first you need to create docker a image for your db server, or use an already existing image.
Bellow is an example of mysql docker image.
version: "3"
services:
****************
mysql:
container_name: mysql
image: mysql:5.7
restart: on-failure
environment:
- MYSQL_DATABASE=YOUR_DB_NAME
- MYSQL_ROOT_PASSWORD=YOUR_ROOT_USER_PASSWORD
- MYSQL_USER=YOUR_USER
- MYSQL_PASSWORD=YOUR_USER_PASSWORD
ports:
- "33060:3306"
volumes:
- "./data/db/mysql:/var/lib/mysql"
Let's describe some sections:
volumes:
- "./data/db/mysql:/var/lib/mysql"
This is like "mounting" container's /var/lib/mysql to system's ./data/db/mysql. So your data will be on your system drive, because in debian the default path to MySQL data is /var/lib/mysql.
ports:
- "33060:3306"
This will map port 3306 from container to system's 33060 port, to avoid conflicts if you have installed MySQL server on system as well.
environment:
- MYSQL_DATABASE=YOUR_DB_NAME
- MYSQL_ROOT_PASSWORD=YOUR_ROOT_USER_PASSWORD
- MYSQL_USER=YOUR_USER
- MYSQL_PASSWORD=YOUR_USER_PASSWORD
This will create a database with the defined parameters: name, root password, ..., or if a database already exists it will try to access with the defined credentials. Functionality to check/create database is already defined in the image.
If you want to define your own functionality you can define your image (e.g. dockerfile: ./Dockerfile instead of image: mysql:5.7). Dockerfile can be something like this:
FROM mysql:5.7
ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD
ENV MYSQL_DATABASE=${MYSQL_DATABASE}
ENV MYSQL_USER=${MYSQL_USER}
ENV MYSQL_PASSWORD=${MYSQL_PASSWORD}
ENV MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
# copy predefined config file
COPY configs/default.cnf /etc/mysql/conf.d/
# To be sure that MySQL will not ignore configs
RUN chmod og-w /etc/mysql/conf.d/default.cnf
# DO SOMETHING ELSE YOU WANT
EXPOSE 3306
CMD ["mysqld"]
So you can build and up your container with command docker-compose up -d --build
Here is an example I used to initialise SQL Server 2017 database using container.
https://www.handsonarchitect.com/2018/01/build-custom-sql-server-2017-linux.html
The trick is to use a shell script to run which will invoke the database initialisation script. You might have to wait for few seconds for the database engine service to start before executing the initialisation script.