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.
Related
I have a couple of questions on password security in mysql container. I use mysql/mysql-server:8.0 image.
The 1st question is
Is using MYSQL_PASSWORD env var in mysql container based on the image above secure?
I elaborate a bit more about this below.
I set mysql password for mysql container by k8s env var injection, that is, setting MYSQL_PASSWORD env var in mysql container by using k8s secrets via env var in k8s manifest file. Is this secure? That is my 1st question. Notes following table in this page say using MYSQL_PWD(note this is not MYSQL_PASSWORD) env var is extremely insecure because ps cmd can display the environment of running processes and any other user can exploit it. Does this also apply to container situation using MYSQL_PASSWORD instead of MYSQL_PWD?
The 2nd question is
Is running mysql -h 127.0.0.1 -p${MYSQL_PASSWORD} in the same mysql container secure?
I need to run similar cmd in k8s readiness probe. The warning section of this page says running mysql -phard-coded-password is not secure. I'm not sure if the password is still not secure even if the env var is used like above and I'm also not sure if this warning applies to container case.
Thanks in advance!
If your security concerns include protecting your database against an attacker with legitimate login access to the host, then the most secure option is to pass the database credentials in a file. Both command-line options and environment variables, in principle, are visible via ps.
For the case of the database container, the standard Docker Hub images don't have paths to provide credentials this way. If you create the initial database elsewhere and then mount the resulting data directory on your production system (consider this like restoring a backup) then you won't need to set any of the initial data variables.
here$ docker run -it -v "$PWD/mysql:/var/lib/mysql" -e MYSQL_PASSWORD=... mysql
^C
here$ scp -r ./mysql there:
here$ ssh there
# without any -e MYSQL_*=... options
there$ docker run -v "$PWD/mysql:/var/lib/mysql" -p 3306:3306 mysql
More broadly, there are two other things I'd take into account here:
Anyone who can run any docker command at all can very easily root the entire host. So if you're broadly granting Docker socket access to anyone with login permission, they can easily find out the credentials (if nothing else they can docker exec a cat command in the container to dump the credentials file).
Any ENV directives in a Dockerfile will be visible in docker history and docker inspect output to anyone who gets a copy of the image. Never put any sort of credentials in your Dockerfile!
Practically, I'd suggest that, if you're this concerned about your database credentials, you're probably dealing with some sort of production system; and if you're dealing with a production system, the set of people who can log into it is limited and trusted. In that case an environment variable setting isn't exposing credentials to anyone who couldn't read it anyways.
(In the more specific case of a Kubernetes Pod with environment variables injected by a Secret, in most cases almost nobody will have login access to an individual Node and the Secret can be protected by Kubernetes RBAC. This is pretty safe from prying eyes if set up correctly.)
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
Greetings and thanks in advance, I'm actually new to docker and docker-compose, watching a lot of videos and reading a lot of articles so far along with trying things.
I've got a front end container and a back end container that build and run alone as a Dockerfile and in a docker-compose setup.
(I've been building with Dockerfile first and then integrating the containers into docker-compose to make sure i understand things correctly)
I'm at the point where i need my database info, since i'll use docker-compose, as i understand it, it should build under the same network with a react front end and django back end.
I have a backup mysql dump file that I'm working with, what i think i need to do is have a container running mysql server and serving out my tables (like I have it locally working). I haven't been able to figure out how to import the backup into my docker mysql container.
Any help is appreciated.
What I've tried so far is using docker in the command line to outline the pieces i'll need in the Dockerfile and then what to move into the docker-compose as mentioned above:
docker run -d --name root -e MYSQL_ROOT_PASSWORD=root mysql # to create my db container
Then I've tried a bunch of commands and permutations of commands, recently in the CLI, here are some of my most recent trials and errors:
docker exec -i root mysql -uroot -proot --force < /Users/homeImac/Downloads/dump-dev-2020-11-10-22-43-06.dmp
ERROR 1046 (3D000) at line 22: No database selected
docker exec -i f803170ce38b sh -c 'exec mysql -uroot -p"root"' < /Users/homeImac/Downloads/dump-dev-2020-11-10-22-43-06.dmp
ERROR 1046 (3D000) at line 22: No database selected
docker exec -i f803170ce38b sh -c 'exec mysql -uroot -h 192.168.1.51 -p"root"' < /Users/homeImac/Downloads/dump-dev-2020-11-10-22-43-06.dmp
ERROR 1045 (28000): Access denied for user 'root'#'homeimac' (using password: YES)
I've scoured the web so far and i'm not sure where to go next, have I got the right idea? If anyone has an example of how to import a database dump (in dmp or dmp.gz), once i get that working, I'll actually do that in the docker-compose file.
Thinking about it, i just have to create the container and import so I might not even need a Dockerfile.
I'll cross that bridge when i get there. This is what I'm thinking though:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: 'app'
etc etc
I've learned a lot super fast, maybe too fast. Thanks for any tips!
The answer to your question is given in the docker hub page of MySQL.
Initializing a fresh instance
When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint->initdb.d. Files will be executed in alphabetical order. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.
In your docker-compose.yml use:
volumes:
- ${PWD}/config/start.sql:/docker-entrypoint-initdb.d/start.sql
and that's it.
Here's the answer that worked for me after working with 2 colleagues that know backend better where I work.
It was pretty simple actually. I created a directory in my repo that would be empty.
I added *.sql and *.dmp to my .gitignore so the dump files would not increase the size of my image.
That directory using docker-compose would be used as a volume under the mysql service:
volumes:
- ~/workspace/app:/workspace/app
The dump file is placed there and is imported into the sql service when I run:
mysql -u app -papp app < /path/to/the/dumpfile
I can go in using docker exec and verify not only the database is there but the tables from my dump file are there as well.
For me, I had to create a new superuser also in my backend container through our Django app.
python3 manage.py createsuperuser
With that, then logging in on localhost:8000/api, everything was linked up between the mysql, backend, and frontend containers.
Hope this helps! I'm sure not all the details are the same for others post volumes, but using volumes, I didn't have to copy any dump file in and it ended up automatically imported and served. That was my big issue.
another way:
docker exec -i containername mysql -uroot -ppassword mysql < dump.sql
from the folder where dump.sql resides
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, ...
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.