Two MySQL docker container - mysql

I have a server that already run a MySQL server container on port 3306:3306 (build from a docker-compose.yml file)
I would like to run another MySQL container on port 3307:3306 from another docker-compose.yml. The problem is that for the second container the MYSQL_ROOT_PASSWORD is never set and I got an access denied.
Both containers are targeting different volumes.
Is it possible to run two MySQL container from two different docker-compose.yml file on the same server?

You are able to run 2 instances of MySQL on the same host and they don't interfere with each other.
What I think is causing your issue is that the environment variable MYSQL_ROOT_PASSWORD (and other environment variables) is only used when the container is started witout an existing database. If a database already exists, then the root password stored in the database is used.
You need to find out what root password was set when the database was created and use that.

The problem is solved.
docker-compose.yml doesn't accept env variable with the char $. To solve it we must escape the char like this : $$.
Thanks for your help guys.

Related

Mysql container password security

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.)

Docker Compose mysql environment variables vs Application .env database variables. Majorly confused

I Have watched approximately 23.74 docker-compose tutorials for laravel and mysql containers!
Please can someone explain to me???
When I create my docker-compose file I create an mysql container from a mysql image.
THEN
I have to enter variables that look like this:
environment:
MYSQL_DATABASE: homestead
MYSQL_USER: homestead
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: secret
SERVICE_TAGS: dev
SERVICE_NAME: mysql
What is the difference between these variables and the variables that I enter into the .env file of my laravel app.
THESE ONES:
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=laradb
DB_USERNAME=root
DB_PASSWORD=secret
WHAT IS THE DIFFERENCE????
What is the docker-compose variables doing. And what are these .env variables doing. And Why am I setting these up twice?
The reason I am asking is because whenever I follow docker tutorials to set up mysql I can only get it to work if I use the variety of variables provided to me by the teacher?? This makes no sense. What about if I want to use my own variable values??!
As soon as I try use my own variables the db breaks and I can't connect to it.
Is homestead some special db instance that is for laravel? This was not an issue when I do it all locally without docker.
For example. The above docker-compose variables were used to create a mysql container and then when i connect to it with SQL workbench I see a schema called 'homestead'. Now what do I do if I don't want that Schema to be called homestead, or what if I want to add another Schema?? It doesn't let me??(permission denied).
I have now spent 3 days trying to create an empty laravel app that connects to a db in a separate container that uses mysql that I can connect to via SQL workbench to see the actual db. I want to be able to create the schema name I want to use in SQL workbench and then be able to set that schema as the db name in my laravel .env file.
Please HELP! You don't have to solve this problem for me but can you point me towards some helpful material that explains this stuff!! For docker-compose specifically mysql. No looking to use std docker commands in the terminal if possible.
.env file vs docker-compose.yml environment::
https://docs.docker.com/compose/env-file
https://docs.docker.com/compose/environment-variables
They have different scopes / precedence.
Passing environment variables in for the benefit of MySQL:
https://hub.docker.com/_/mysql
The MySQL container expects those environment variables to exist and have values.
Likewise for the Laravel container needs to be able to talk to the MySQL container, hence it needs the values to match and that is why there is overlap.
The bash command printenv might help tighten this up, as you can see what environment variables are exposed to which containers (docker run msql_container_name bash -c 'printenv' vs docker run laravel_container_name bash -c 'printenv').
https://github.com/reflexions/docker-laravel (as an example)
You've mentioned you don't mind being sent to references, so I've primarily done that - but I'm happy to elaborate in here or in comments if it still isn't making sense / I'm not addressing the main issue.

Docker. Create image based on MySQL with DB and User created

I want to create an image with docker for my app.
The app uses MySQL. I need my image to be based on MySQL image (mysql/mysql-server ?) .
IN the Dockerfile i need to set some instructions to create a DB with specific user/password . So, my app can work with that DB .
I don't need tables, only empty DB with specific name and user/password that can access this DB.
How can i do this?
I wanted something like
FROM mysql/mysql-server
# Create MySQL DB
mysql -u root -e "CREATE DATABASE MyDB"
But i don't know root user password here. It seems it is autogenerated ?
How can i do this?
That image auto-generates the root password by default, as stated in the image github repository (https://github.com/mysql/mysql-docker). You can set the MYSQL_ROOT_PASSWORD environment variable in your Dockerfile with the password you want.
Apart from that, if what you want is to create a database at image startup, you can use the environment variable MYSQL_DATABASE.
More info about the supported environment variables here:
https://github.com/mysql/mysql-docker#docker-environment-variables
You have 2 solutions here:
[Easy] Using the docker-compose and create a docker-compose.yml file like this one:
version: '3'
services:
mariadb:
container_name: mariadb
image: mariadb:latest
environment:
- MYSQL_DATABASE=_YOUR_DB_
- MYSQL_ROOT_PASSWORD="_YOUR_PASSWORD_"
- MYSQL_USER=_YOUR_USER_
- MYSQL_PASSWORD=_YOUR_USER_PASSWORD_
...
This configuration will bring a MariaDB database to you. also if you want to use it, you can simply check this page for the installation guide:
https://github.com/docker/compose
The final step is just to go into the directory you saved the docker-compose.yml and just run:
docker-compose up
or if you don't want to see the log inside the terminal just add -d flag to it.
2. [Little Complicated] You can create a custom image for your needs. in this case, it is better if you check the Dockerfile documents and then see this autogenerated default MariaDB Dockerfile for understanding what to do exactly to achieve your goal.

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.