Docker doesn't set MariaDB password - docker

In my docker-compose.yml
version: '3'
services:
db:
image: mariadb:latest
volumes:
- ./dc_test_db:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: secret
When I connect via:
sudo docker exec -it docker_db_1 mysql -u root -p
I have to let the password empty to login. What is wrong?

I had this problem in version 10.4 of mariadb which was fixed by changing to version 10.3.
But there can be another reason for this problem.
In Docker architecture, it should be noted that images are immutable after the first build. That is, by changing the local variables defined in the docker compose file and re-running the service or re-uping the service, there will be no change in the initial settings of the builded image. To apply these changes, the steps of building the image and container and running the service must be performed again. Which can be done as follows.
1.docker-compose stop (First we stop the service)
2.Docker-compose rm (Then we clean all the related containers)
3.Docker-compose up --build -d (Finally run the service with the --build option to rebuild the images with the newly defined settings.)
Note that performing these steps will erase all data stored inside the containers.

It seems you are starting the mariadb container from an existing db data directory, this will result in using the current database instead of initializing a new one. So to solve this I would suggest to remove any existing mariadb container, remove the current db directory content, run the docker compose again:
$ docker-compose down -v
$ rm -Rf dc_test_db/*
$ docker-compose up -d

That is because you are using the client locally from inside the container itself. The local connection doesn't ask for password.
Try to connect from your host computer to the docker containerip:3306 and then it will ask for password

MySQL user is defined by username and host that request come from. For example, there is three different user root#192.168.0.123, root#localhost and wildcard root#%.
If you set MYSQL_ROOT_PASSWORD env in docker-compose file, your mariadb will set password for user root#%, not password for user root#localhost.
But when you try to test password of mariadb, you use sudo docker exec -it docker_db_1 mysql -u root -p command, it mean mariadb-client in container will use user root#local (without password) to access mariadb-server, not user root#%(that have password you set before).
So if you want to test password you set for that user, use that command:
docker run -it mariadb mysql -u root -h MARIADB-CONTAINER-IP -p
MARIADB-CONTAINER-IP is ip address of your mariadb container.(use docker inspect to check ip address of container).
Thanks.

MYSQL_ROOT_PASSWORD will only be set during 1st time running the container with the given volume.
To set the password using MYSQL_ROOT_PASSWORD:
Option1: delete old DB files and start fresh.
rm -rf ./dc_test_db
Option2: use named volume:
version: '3.5'
services:
db:
image: mariadb:latest
volumes:
- dc_test_db:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
dc_test_db:

Related

Why does MariaDB docker container not require a password from the host, but does from inside the container?

Have a very odd occurrence with MariaDB Container (10.9 latest image) spun up using a docker-compose file.
The container all works, if I access the container's shell I can run mysql -u root -p and use my password to access mysql.
I patch port 3306 through to my M2 Mac and I get " Access Denied for root#'localhost' " when trying mysql -h 127.0.0.1 -u root -p and the same password.
If however I leave the password field blank, it connects. I'am at a loss why though!
I thought it may be something like root#'%' having a blank pwd, but I have tried setting that to the same password. But either way I would expect the Access denied message to say I was using root#'%'
I have tried rebuilding the images, deleting the volumes. I found a github issue around the MYSQL_PWD being blank, so I have added that in for good measure, but it still doesn't play nicely.
db:
image: mariadb:latest
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: dev_db
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_PWD: password
ports:
- "3306:3306"
volumes:
- data-volume:/var/lib/mysql
Has anyone come across this before, or have any suggestions how to resolve it? It is like the root#'localhost' is somehow configured with two different credentials?
When you connect to mysql/mariadb inside a container, that instance does not see you as coming from 'localhost'. See below how you can test that. So if you see an error saying 'root'#'localhost' that is most definitely because you are connecting to a process running on host, not inside the container.
Run the test container
docker run -d --rm --name testmariadb -P \
-e MYSQL_RANDOM_ROOT_PASSWORD=true \
mariadb:latest
Check the port:
export MARIADB_PORT=$(docker inspect testmariadb --format='{{range $k, $v := .NetworkSettings.Ports}}{{with index $v 0}}{{.HostPort}}{{end}}{{end}}')
echo Container running on port ${MARIADB_PORT}
Try to connect and check the error
mysql -h127.0.0.1 -P${MARIADB_PORT} -uroot
You should see something similar to:
ERROR 1045 (28000): Access denied for user 'root'#'172.17.0.1' (using password: NO)
Cleanup
docker container rm -f testmariadb

How to move docker volume to disk location?

I have a MySQL docker image running in a docker container on Ubuntu VPS. I bring up MySQL using the docker-compose up -d command via the following docker-composer.yml file
version: "3"
services:
mysql_server:
image: mysql:8.0.21
restart: always
container_name: mysql_server
environment:
MYSQL_DATABASE: db_name
MYSQL_USER: db_username
MYSQL_PASSWORD: db_password
MYSQL_ROOT_PASSWORD: root_password
volumes:
- mysql_server_data:/var/lib/mysql
- /mysql/files/conf.d:/etc/mysql/conf.d
I am having some performance issues and would like to do the following in attempt to improve performance.
I want the data in the mysql_server_data volume to be mounted on /mysql/data without losing any data as this instance in running in production.
I also want to mount the MySQL config file on /mysql/files so I can change the instance configuration to increase performance.
Questions
How can change the data location of a the volume from mysql_server_data to /mysql/data?
Also, how can I mount MySQL's config file on /mysql/files/conf.d to allow me to update the settings?
I tried to mount config file like this
volumes:
- /mysql/files/conf.d:/etc/mysql/conf.d
But that created a directory /mysql/files/conf.d with no config file.
To move the data:
Shutdown the container with docker-compose down, then on the local file system, copy the data from mysql_server_data to /mysql/data. Then change the compose file to reflect the new location. Finally restart the container with docker-compose up.
To mount the config files, as per the docker hub documentation for MySQL, If /my/custom/config-file.cnf is the path and name of your custom configuration file, the your volume map is:
/my/custom:/etc/mysql/conf.d
Note that mapping the volume to the container does not bring the data from your container to you local, but the other way around. So if you want to have the file in the container, you must first create it on your local.
Use the trick suggested by Docker maintainer Sebastiaan van Stijn at https://github.com/moby/moby/issues/31417 to send the tar over stdout:
docker run --rm -v vol_name:/vol_path img_name sh -c 'tar -cOzf - /vol_path' > volume-export.tgz

How to implement changes made to docker-compose.yml to detached running containers

The project is currently running in the background from this command:
docker-compose up -d
I need to make two changes to their docker-compose.yml:
Add a new container
Update a previous container to have a link to the new container
After changes are made:
NOTE the "<--" arrows for my changes
web:
build: .
restart: always
command: ['tini', '--', 'rails', 's']
environment:
RAILS_ENV: production
HOST: example.com
EMAIL: admin#example.com
links:
- db:mongo
- exim4:exim4.docker # <-- Add link
ports:
- 3000:3000
volumes:
- .:/usr/src/app
db:
image: mongo
restart: always
exim4: # <-------------------------------- Add new container
image: exim4
restart: always
ports:
- 25:25
environment:
EMAIL_USER: user#example.com
EMAIL_PASSWORD: abcdabcdabcdabcd
After making the changes, how do I apply them? (without destroying anything)
I tried docker-compose down && docker-compose up -d but this destroyed the Mongo DB container... I cannot do that... again... :sob:
docker-compose restart says it won't recognize any changes made to docker-compose.yml
(Source: https://docs.docker.com/compose/reference/restart/)
docker-compose stop && docker-compose start sounds like it'll just startup the old containers without my changes?
Test server:
Docker version: 1.11.2, build b9f10c9/1.11.2
docker-compose version: 1.8.0, build f3628c7
Production server is likely using older versions, unsure if that will be an issue?
If you just run docker-compose up -d again, it will notice the new container and the changed configuration and apply them.
But:
(without destroying anything)
There are a number of settings that can only be set at container startup time. If you change these, Docker Compose will delete and recreate the affected container. For example, links are a startup-only option, so re-running docker-compose up -d will delete and recreate the web container.
this destroyed the Mongo DB container... I cannot do that... again...
db:
image: mongo
restart: always
Add a volumes: option to this so that data is stored outside the container. You can keep it in a named volume, possibly managed by Docker Compose, which has some advantages, but a host-system directory is probably harder to accidentally destroy. You will have to delete and restart the container to change this option. But note that you will also have to delete and restart the container if, for example, there is a security update in MongoDB and you need a new image.
Your ideal state here is:
Actual databases (like your MongoDB container) store data in named volumes or host directories
Applications (like your Rails container) store nothing locally, and can be freely destroyed and recreated
All code is in Docker images, which can always be rebuilt from source control
Use volumes as necessary to inject config files and extract logs
If you lose your entire /var/lib/docker directory (which happens!) you shouldn't actually lose any state, though you will probably wind up with some application downtime.
Just docker-compose up -d will do the job.
Output should be like
> docker-compose up -d
Starting container1 ... done
> docker-compose up -d
container1 is up-to-date
Creating container2 ... done
As a side note, docker-compose is not really for production. You may want to consider docker swarm.
the key here is that up is idempotent.
if you update configuration in docker-compose.yaml
docker compose up -d
If compose is building images before run it, and you want to rebuild them:
docker compose up -d --build

docker, MYSQL_ROOT_PASSWORD do not work

docker-compose:
mysql:
image: mysql:5.7.16
container_name: f_mysql
volumes:
- ./db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: sheep
expose:
- '3306'
and I use docker exec input this container,
and I type echo $MYSQL_ROOT_PASSWORD, then I got sheep,
but the mysql root password still is '',
when I type 'mysql -uroot', I login mysql.
For me the issue was that I'd created the db volume with the random password option set, then disabled that, but hadn't cleared the volume. So no matter what changes I made to the docker-compose file, the old volume with the old login information was still there.
I had to docker volume ls to find the volume then docker volume rm <name> to remove it. After re-upping, everything worked.
Regarding other answers on this page, the format for specifying env variables is correct, you can use either
environment:
MYSQL_ROOT_PASSWORD: a_password
OR
environment:
- MYSQL_ROOT_PASSWORD=a_password
The image entrypoint script will never make changes to a database which is existing. If you mount an existing data directory into var/lib/mysql then MYSQL_ROOT_PASSWORD will have no effect.
Workaround
Remove all unused volumes: docker volume prune
Remove the volume from your database service: docker volume rm <db_data>
Down containers, remove volumes: docker-compose down --volumes
You need to fix your docker-compose file:
environment:
- MYSQL_ROOT_PASSWORD=sheep
The following is the full docker-compose that achieves what you want:
version: '2'
services:
mysql:
image: mysql:5.7.16
container_name: f_mysql
volumes:
- ./db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=sheep
expose:
- '3306'
Then with a docker exec -it f_mysql /bin/bash and inside the container mysql -u root -p, using sheep, as the password, will be the only way to connect to the mysql server.
This happens when your volume from a directory has wrong permission.
You can fix this letting docker to create directory itself.
In case you have an existent data, you can compare the new one with the previous one in order to apply correct chmod, because this depends on if docker/your-user is part of root group.
Please note that according to the official docker image: "none of those variables will have any effect if you start the container with a data directory that already contains a database". In fact, in this case, you have already a "mysql.user" table, and you should use the user info set there that there. The same thing happens when you try to restore a full dump.
This happened when the the mount directory has ea(extended attribute) on Mac.
It is better to delete the directory once and recreate it or check the permission with the xattr command.
$ ls -l ./db
$ xattr ls ./db
I had a same problem, and after a lot of try I found my solution. When I run first time the docker-composer, I left everything on the original settings like this:
environment:
MYSQL_ROOT_PASSWORD: MYSQL_ROOT_PASSWORD
Then I change the password, say "docker-compose up" but it was still MYSQL_ROOT_PASSWORD.
My solution was delete the "mysql" docker image from my disk. After that, the docker download everything again BUT also set my password for the root as well. Maybe this is not the best, but I am also a beginner in Docker.
So in nutshell the simple "docker-compose up" does not enough.

Difference between docker-compose and manual commands

What I'm trying to do
I want to run a yesod web application in one docker container, linked to a postgres database in another docker container.
What I've tried
I have the following file hierarchy:
/
api/
Dockerfile
database/
Dockerfile
docker-compose.yml
The docker-compose.yml looks like this:
database:
build: database
api:
build: api
command: .cabal/bin/yesod devel # dev setting
environment:
- HOST=0.0.0.0
- PGHOST=database
- PGPORT=5432
- PGUSER=postgres
- PGPASS
- PGDATABASE=postgres
links:
- database
volumes:
- api:/home/haskell/
ports:
- "3000:3000"
Running sudo docker-compose up fails either to start the api container at all or, just as often, with the following error:
api_1 | Yesod devel server. Press ENTER to quit
api_1 | yesod: <stdin>: hGetLine: end of file
personal_api_1 exited with code 1
If, however, I run sudo docker-compose database up & then start up the api container without using compose but instead using
sudo docker run -p 3000:3000 -itv /home/me/projects/personal/api/:/home/haskell --link personal_database_1:database personal_api /bin/bash
I can export the environment variables being set up in the docker-compose.yml file then manually run yesod devel and visit my site successfully on localhost.
Finally, I obtain a third different behaviour if I run sudo docker-compose run api on its own. This seems to start successfully but I can't access the page in my browser. By running sudo docker-compose run api /bin/bash I've been able to explore this container and I can confirm the environment variables being set in docker-compose.yml are all set correctly.
Desired behaviour
I would like to get the result I achieve from running the database in the background then manually setting the environment in the api container's shell simply by running sudo docker-compose up.
Question
Clearly the three different approaches I'm trying do slightly different things. But from my understanding of docker and docker-compose I would expect them to be essentially equivalent. Please could someone explain how and why they differ and, if possible, how I might achieve my desired result?
The error-message suggests the API container is expecting input from the command-line, which expects a TTY to be present in your container.
In your "manual" start, you tell docker to create a TTY in the container via the -t flag (-itv is shorthand for -i -t -v), so the API container runs successfully.
To achieve the same in docker-compose, you'll have to add a tty key to the API service in your docker-compose.yml and set it to true;
database:
build: database
api:
build: api
tty: true # <--- enable TTY for this service
command: .cabal/bin/yesod devel # dev setting

Resources