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
Related
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.
I need to have to database created at startup in one service. F.e.:
services:
db:
image: percona:5.7.24-centos
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: db1
MYSQL_DATABASE_1: db2
MYSQL_PASSWORD: password
network_mode: "host"
But unfortunatelly only one is supported using image/environment variable: MYSQL_DATABASE.
I am using this in docker-compose
Can I ask for help?
So write your own Dockerfile and copy the sql script which will create a new database onto the image.
Something like below
FROM mysql
ENV MYSQL_DATABASE=test \
MYSQL_ROOT_PASSWORD=password \
ADD yourscript.sql /docker-entrypoint-initdb.d/
EXPOSE 3306
So all the scipts inside /docker-entrypoint-initdb.d/ will be executed at container startup. In effect, your second database creation script would go inside yourscript.sql which will be executed on container startup
You can build the image using the command
docker build -t masterdanny/percona:5.7.24-centos
and then use that new image in your docker-compose file
Cheers. Let me know if you have any questions.
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.
This is what I see when I am in the container created by docker-compose:
mysql> SELECT user FROM mysql.user;
+------+
| user |
+------+
| root |
+------+
1 row in set (0.00 sec)
root#541e4d686184:/# echo $MYSQL_USER
dbuser
So dbuser is not present in the users table even though the $MYSQL_USER is set properly .
In docker-compose.yml I have this:
version: '2'
services:
db:
image: mysql:latest
environment:
MYSQL_DATABASE: mydb
MYSQL_USER: dbuser
MYSQL_PASSWORD: userpass
MYSQL_ROOT_PASSWORD: password
ports:
- "3306"
volumes:
- ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
- my-datavolume:/var/lib/mysql
volumes:
my-datavolume:
I expected dbuser to be created automatically, but that didn't happen.
I also have a sql file to create my database and tables if they don't already exist, but right now tomcat can't connect to my database.
Same symptoms as this question, but I am already using a dictionary for my usernames/passwords.
UPDATE:
I am getting close. When inside container I manually did:
/docker-entrypoint-initdb.d/create_users.sh
Then the user was created inside MySQL table and I was able to deploy my application to my tomcat server and I didn't get an error about dbuser being denied access.
So, why did I have to run this command myself, it should be run by docker-compose, according to the mysql docker docs under Initializing a fresh instance.
How about:
docker-compose down -v
From the documentation:
-v - Remove volumes declared in the volumes section of the Compose file.
Your database has been already created inside a volume, so any changes of initial settings in docker-compose.yml won't be reflected.
In case you want to remove just a single volume, you may use docker volume ls to list all existing volumes and then docker volume rm <VOLUME NAME> to remove it.
Note: Bind mounts are not removed with the -v flag, so in case you are using them instead of volumes, you'll have to manually delete folders containing MySQL data. In docker-compose bind mounts are created whenever you provide a source path in your volumes section (eg. /my-path:/var/lib/mysql).
Worked for me : stop docker and remove manually all the folder containing MySQL data from previous builds.
Also : don't forget to add a MYSQL_DATABASE environment var or it won't create the user you specified.
Github issue
Important to note that the image entrypoint script will never make
changes to an existing database. If you mount an existing data
directory into var/lib/mysql, options like MYSQL_ROOT_PASSWORD will
have no effect
I met the same issue, you may try to remove everything under 'my-datavolume' because the environment works only in the initial stage that means there should not any data in '/var/lib/mysql'. This approach worked for me.
What worked for me is:
docker-compose down
docker volume ls
docker volume rm <volume-name>
docker-compose up -d
In the newly created volume, my user was there.
after my testing,
create init.sql and links to /docker-entrypoint-initdb.d
docker-compose down
docker volume ls
docker volume rm
docker-compose up -d
then everythi is ok
I am trying to create a mysql database/schema if it doesn't already exist.
Here is what I have tried:
docker-compose.yml
mysql:
image: mysql:5.6.26
environment:
- MYSQL_ROOT_PASSWORD=root
command: "mysql -uroot -proot < createDB.sql"
ports:
- "3306:3306"
createDB.sql
CREATE DATABASE IF NOT EXISTS bignibou;
It does not work. What would be the best way to use docker/docker-compose in order to create a schema if it does not exist?
I finally found the beginning of a solution.
The MySQL image takes an environment variable i.e. MYSQL_DATABASE that initialize the container with the name of the database on image startup See here for full documentation.
Or read the excerpt below:
MYSQL_DATABASE
This variable is optional and allows you to specify the name of a
database to be created on image startup. If a user/password was
supplied (see below) then that user will be granted superuser access
(corresponding to GRANT ALL) to this database.
Here is what I came up with:
mysql:
image: mysql:5.6.26
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=bignibou
ports:
- "3306:3306"
I now need a way to specify the default collation but that is another story...
edit: For those interested in specifying a different collation from the default, here are the instructions to use another config file that will override the default one. See below:
Using a custom MySQL configuration file The MySQL startup
configuration is specified in the file /etc/mysql/my.cnf, and that
file in turn includes any files found in the /etc/mysql/conf.d
directory that end with .cnf. Settings in files in this directory will
augment and/or override settings in /etc/mysql/my.cnf. If you want to
use a customized MySQL configuration, you can create your alternative
configuration file in a directory on the host machine and then mount
that directory location as /etc/mysql/conf.d inside the mysql
container.
If /my/custom/config-file.cnf is the path and name of your custom
configuration file, you can start your mysql container like this (note
that only the directory path of the custom config file is used in this
command):
$ docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e
MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag This will start a new
container some-mysql where the MySQL instance uses the combined
startup settings from /etc/mysql/my.cnf and
/etc/mysql/conf.d/config-file.cnf, with settings from the latter
taking precedence.
To not lost your data better use volumes as well:
version: '3'
services:
db:
image: mysql:5.7
volumes:
- mysql-db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: my_db_name
ports:
- "3307:3306"
volumes:
mysql-db:
probably what you are trying to do needs an additional script. So if building an image instead of directly using a prebuilt image is an option for you, you need to use a Dockerfile and use a script file which first imports the script in MySql and then runs the service itself.
take a look at this answer: Docker - Initialize mysql database with schema
From the docker-compose documentation - see Define Services - you can tell which Dockerfile it will use to build the image. Therefore you can create a Dockerfile based on the mysql image and create the database inside it using standard Dockerfile commands.
This might be useful in case someone lands here in future. The real issue appears to be the "command" statement in the docker-compose file. Once the command finishes successfully the container will get destroyed. This sql script must be run only after docker-compose has run and containers have been created. docker-compose "command" is really to start a service in the container. In this case you overrode the mysql service with your command.