MySQL Docker Container storing password after first run - mysql

All my experience with Docker so far has led me to believe that containers are stateless.
If so, why is my container storing the password that I change it to after the first run if I spun it up without specifying a volume or bind mount? I am especially puzzled since none of the other edits I make to the dbms persist (like creating tables).
Additional Details:
Versions:
1. Docker - 18.09.0 build 4d60db4
2. Image - mysql/mysql-server:latest
Commands:
1. $ docker run --name=sql -d mysql/mysql-server:latest
2. $ docker logs sql 2>&1 | grep GENERATED to grab the generated password for first login
3. $ docker exec -it sql mysql -uroot -p
4. mysql> Enter Password: <generated password>
5. mysql> ALTER USER 'root'#'localhost' IDENTIFIED BY 'stkoverflw';
6. mysql> exit
7. $ docker stop sql
8. $ docker start sql
9. $ docker exec -it sql mysql -uroot -p
10. mysql> Enter Password: <stkoverflw>
How does the password configuration persist across restarts of the container?

Containers are not stateless. Containers are easy to create and destroy, so they can be used to run a service which is stateless, but each container is itself stateful.
When the container is running, there is a volume containing its root filesystem. You don't have to tell Docker to create it. Docker has to create it because otherwise where do the container's files go?
When you say docker stop, the container stops running but it is not destroyed. When you say docker start, the same container resumes with the same root volume. That's where the changed password persists. The process running in the container was stopped and a new process was started (so state held in memory would be lost), but the filesystem is still there.
To get rid of a container (including the changed password), say docker rm. Then you can say docker run to start from scratch.

Related

How to get download a sql dump from docker MYSQL container from terminal

How to get download a SQL dump from docker MYSQL container from terminal
Version: mysql:5.7
I need to download a SQL dump, from the docker container. The database is available inside the docker container.
First we should be aware of running MySQL container host & port.
If you are not aware of it, please refer this link How to Find Running Docker container host & port
This is the command to download the mysql dump in terminal
mysqldump -u root -p --column-statistics=0 --host=0.0.0.0 --port=3310 local_db > localDb04Dec2021.sql
Why we have added in this flag --column-statistics=0 Refer this link to know mysqldump: Couldn't execute. Unknown table 'column_statistics' in information_schema
Hostname for this container is 0.0.0.0
Port 3310
local_db is the name of the mysql database
Dump file name is localDb04Dec2021.sql
After run this command the dump will be available is the path, which you are running this command
If you not aware of the current path, get to know by hit this pwd command

Where docker stores mysql settings

I am facing one issue with docker, L am using laradock docker env for laravel. Since it has issue with mysql version I had to run those command:
$ docker-compose exec mysql bash
$ mysql -u root -p
ALTER USER 'root'#'localhost' indentified WITH mysql_native_password BY 'root';
Also imported database through http://localhost:8080 and phpmyadmin
So I am trying to reproduce this issue again, so I deleted everything from docker with
$ docker system prune
but when I rebuild the containers
sudo docker-compose up -d nginx mysql phpmyadmin workspace
My previous database is loaded again.
So my question would be how to delete db and MySQL settings, so I can execute the alter command and import database again.
Overall I am trying to determine if this issue with MySQL will occur on another platform again, so I am trying to reproduce it from scratch and that is why I need to reset completely MySQL env and databases.
So not sure where MySQL settings are stored and how to delete them.
MySQL is storing most of the important information of your container in a volume.
Now, the command:
docker system prune
do not remove the volumes, per default.
If you also want to remove them, you can run:
docker system prune --volumes
If you do want to list or act on those specific volumes:
docker volume --help
would give you all the commands on volumes like rm, ls, ...

Connecting to mysql container from host

I have installed docker on my mac. I have MySQL container which is running on my local machine (MAC).
Docker ps command is giving me below output -
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5c50b2d334a test_mysql2 "docker-entrypoint.s…" 2 hours ago Up 2 hours (healthy) 0.0.0.0:32783->3306/tcp test_mysql2_1
I know username and password to the mysql which would be setup up in the container.
I want to connect to mysql and run some queries But I am not able to figure out how to connect to it. Any help will be appreciated.
Do you want to Connect to MySQL through Docker if yes; Kindly follow this step by step procedure that I am using.
Step 1 : Pull MySql image from docker hub. The following command will pull the latest mysql image.
cli> docker pull mysql
Step 2: Run a container from this image. ‘-name’ gives a name to the container. ‘ -e’ specifies run time variables you need to set. Set the password for the MySQL root user using ‘MYSQL_ROOT_PASSWORD’. ‘-d’ tells the docker to run the container in background.
cli> docker run --name=testsql -e MYSQL_ROOT_PASSWORD=rukshani -d mysql
This will output a container id; which means that the container is running in the background properly.
Step 3: Then check the status of the container by issuing, ‘docker ps’ command
cli> docker ps
Now you should be able to see that MySQL is running on port 3306.
Step 4: To checkout the logs of the running container use the following command
cli > docker logs testsql
Step 5: Find the IP of the container using following. Check out the “IPAddress” from the output, this will tell you the IP address.
cli> docker inspect testsql
Now you should be able to connect to MySQL using tIPs ip address on port 3306.
Base on what I understand from your question, this is what you need. (I hope so)
(This is not my own documentation, I only like to document everything most especially those procedure that I cannot put in my head, so that if ever the same thing happen or I need same procedure in the future, I will not waste my time to research again, but instead I will open my notes and run the commands.)
As you can see in the output of docker ps, the port 32783 (local machine) is mapped to the port 3306 inside the docker container. If you are using a MySQL Client (e.g. MySQL Workbench) you should be able to connect using ip localhost and port 32783. If not, you should go with docker exec and then open a interactive mysql shell inside the container (As mulg0r commented).

MySQL container: grant access and create a new image

I'm trying to use MySQL docker container in my host system to make installation and configuration processes much easier and faster.
So, I've pulled an image from:
https://hub.docker.com/r/mysql/mysql-server/
Then started container based on this image..
Container started fine, but I was not able to connect to this DB from my host system (everything is ok if I try to connect from container). It failed with a message:
ERROR 1130 (HY000): Host '<here goes my IP>' is not allowed to connect to this MySQL server
So, as I understand, my root user has no enough permissions.
I've entered my container:
docker exec -it mysql bash
Connected to DB:
mysql -uroot -ppassword
Updated permissions for my root user:
use mysql;
UPDATE user SET Host="%" WHERE User='root';
It's updated fine.
Than I decided to save my updated image somehow... I've found this guide:
http://docs.oracle.com/cd/E52668_01/E75728/html/section_c5q_n2z_fp.html
After executing:
docker stop mysql
docker commit -m "Fixed permissions for root user" -a "Few words about author" `docker ps -l -q` myrepo/mysql:v1
docker rm mysql
docker run --name new-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=pass -d myrepo/mysql:v1
I've found that my root user hasn't permissions again.
What is wrong here?
How to public my updated image into my Dockerhub?
My original answer is for persisting the change in the MySQL data after it has been initialized. But since you want to do this in the image for every initialization automatically there is a different approach for this. You can use one of the following options:
There is an environment variable called MYSQL_ROOT_HOST for this image where you can set the host (https://github.com/mysql/mysql-docker/blob/mysql-server/5.7/docker-entrypoint.sh#L63-L69). You should be able to set this to % to allow all hosts to connect as root such as -e MYSQL_ROOT_HOST="%".
The image supports adding SQL files to /docker-entrypoint-initdb.d/ to be initialized on startup (https://github.com/mysql/mysql-docker/blob/mysql-server/5.7/docker-entrypoint.sh#L98-L105). You can create your SQL file that has UPDATE mysql.user SET Host="%" WHERE User='root'; in it and then ADD that file to /docker-entrypoint-initdb.d/ in your own image. Then, when starting a container based on that image it will initialize that SQL file.
That image specifies a default volume to hold the MySQL data at https://github.com/mysql/mysql-docker/blob/mysql-server/5.7/Dockerfile#L11. When you start the container, a volume is created for that container. When you update the permissions for the root user, it is saved in this volume (it is actually part of MySQL data for the mysql database). But once you remove the container, that volume is also lost.
There are usually two things you can do in this case to preserve the data between container restarts or even new containers:
Create a named volume and mount the data there. To do this you can run docker volume create mysqldata. Then, when starting the container mount the data with -v mysqldata:/var/lib/mysql. This volume will persist even after you stop or delete your MySQL container.
Bind mount the data to a host folder. Instead of creating a volume, you can just mount a folder such as -v /mnt/mysqldata:/var/lib/mysql. This will persist all your MySQL data on the host at /mnt/mysqldata.
Though, these are not the only ways to persist data, they are two built-in methods. There are also Docker volume plugins that allow you to use other storage mediums (examples might be https://github.com/rancher/convoy for NFS and https://github.com/NetApp/netappdvp for NetApp).
docker exec -it mysql bash
chown -R mysql:mysql /var/lib/mysql
if you change permission of volume in host, above code will correct permission denied for root.

Lost connection to MySQL server when creating database from script in a Docker container

I'm setting an script to configure Docker environments for developer local machines. A specifically part of the script consists to create a temporary container with a local volume to set the database i'll use in next step. this is the code used in the script:
docker run -d --name mysql_temp -v ~/dev/mysql:/var/lib/mysql/data -e MYSQL_ROOT_PASSWORD=test -p 3306:3306 centos/mysql-57-centos7:latest
the next step in the script is this line:
mysql -u root -h 127.0.0.1 --protocol=tcp --password=test -e "CREATE DATABASE db_test;"
then, the script returns me this error:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 2
Curiously, if i force the exit with exit command after the first command and i execute the second one by my hand, directly in the terminal, it works and creates me the database.
Any idea what is this happening?
thanks in advance,
In your script, when the first line executes, it creates the docker container. But it takes time to initialise the mysql server on the container. The script executes the second line without waiting for mysql to initialise. Hence it cannot connect.
I'm assuming you have written a shell script. Try the following script.
docker run -d --name mysql_temp -v ~/dev/mysql:/var/lib/mysql/data -e MYSQL_ROOT_PASSWORD=test -p 3306:3306 centos/mysql-57-centos7:latest
sleep 10
mysql -u root -h localhost --protocol=tcp -ptest -e "CREATE DATABASE db_test;"
Note the second line having sleep 10. Basically this will create a delay of 10 seconds before executing the next command. Try varying the sleep time to higher if it still doesn't work.
Also change 127.0.0.1 to localhost and --password=test to -ptest
Note: You said that if you exit the script and run the mysql command manually, it works. Thats because by the time you tried running manually, the container has initialised mysql. Try running the docker run command in one terminal window. Once the container starts, try running the mysql command immediately in another terminal window to see if it works as quickly as you expected.