Docker compose database url environment variable for flask app - mysql

Trying to use docker-compose.yml instead of starting the containers separately like so:
docker container run --name mysql -d -e MYSQL_RANDOM_ROOT_PASSWORD=yes -e MYSQL_DATABASE=currency -e MYSQL_USER=currency -e MYSQL_PASSWORD=currency mysql/mysql-server:5.7
docker run --name currency -d -p 8000:5000 --rm --link mysql:dbserver -e DATABASE_URL=mysql+pymysql://currency:currency#dbserver/currency currency:latest
When run separately, the flask app correctly finds the DATABASE_URL and uses mysql db.
The docker-compose.yml file which I used is below:
version: "2"
services:
mysql:
image: mysql/mysql-server:5.7
environment:
- MYSQL_RANDOM_ROOT_PASSWORD:yes
- MYSQL_DATABASE:currency
- MYSQL_USER:currency
- MYSQL_PASSWORD:currency
currency:
build: .
links:
- "mysql:dbserver"
ports:
- "8000:5000"
environment:
- DATABASE_URL:"mysql+pymysql://currency:currency#dbserver/currency"
When I use docker-compose.yml, it is not using the mysql db. I believe for some mistake in docker-compose.yml, the flask app is not able see the environment variable "DATABASE_URL". What is going wrong in the docker-compose.yml?

First: make sure to not use links
The --link flag is a legacy feature of Docker. It may eventually be removed. Unless you absolutely need to continue using it, we recommend that you use user-defined networks to facilitate communication between two containers instead of using --link.
One feature that user-defined networks do not support that you can do with --link is sharing environmental variables between containers. However, you can use other mechanisms such as volumes to share environment variables between containers in a more controlled way.
Second, do a docker exec -it currency bash to open a session in your currency container, and do an echo "DATABASE_URL='${DATABASE_URL}'" in it, to check the environment variable has been set.
Finally, check in your case if this is an ordering issue (currency starting before the database is fully up)
See "Control startup order in Compose".
For instance:
version: "2"
services:
web:
build: .
ports:
- "80:8000"
depends_on:
- "db"
command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]
db:
image: postgres

Related

Passing extra commands to a docker image from bitbucket-piplines.yml

Trying to set the default charset and collation of a mysql:5.7 docker image using Bitbucket Pipelines, the documentation is a little vague mentioning:
If you need to configure the underlying database engine further, refer to the official Docker Hub image for details.
This page that the bitbucket documentation sends you to suggests that it is possible... at least via docker:
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
So my question is how do I pass these parameters in: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
I have seen people use command: parameter in the YML for bitbucket-pipelines however the pipeline config editor on bitbucket says it's not valid there:
definitions:
services:
mysql:
image: mysql:5.7
command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']
ports:
- "3306:3306"
variables:
MYSQL_DATABASE: $MY_DATABASE
MYSQL_ROOT_PASSWORD: $MY_PW
It seems that it is not possible to pass commands to containers that run as services at this point. I was able to find the schema of the YAML file that defines the pipelines (check line 365). Not only you can't set the command, but you also can't set the ports. Fortunately, 3306 is the default one.
As as workaround I'd suggest you build your own Docker image, based on the mysql:5.7 and change the CMD statement to mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci (you can see how the mysql image's CMD look's like from here). After that, you have to push the image to a registry to which your Bitbucket runner has access to and use this image for your pipeline.
The following Dockerfile might do the job for you:
FROM mysql:5.7
CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
At the end, your definition will look like this:
definitions:
services:
mysql:
image: your-custom-mysql-image:5.7
variables:
MYSQL_DATABASE: $MY_DATABASE
MYSQL_ROOT_PASSWORD: $MY_PW

cann't connect to the mysql docker container following the official instructures

Following steps in https://hub.docker.com/_/mysql/:
Start a mysql server instance
Starting a MySQL instance is simple:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d
mysql:tag
... where some-mysql is the name you want to assign to your container,
my-secret-pw is the password to be set for the MySQL root user and tag
is the tag specifying the MySQL version you want. See the list above
for relevant tags. Connect to MySQL from the MySQL command line client
The following command starts another mysql container instance and runs
the mysql command line client against your original mysql container,
allowing you to execute SQL statements against your database instance:
$ docker run -it --network some-network --rm mysql mysql -hsome-mysql
-uexample-user -p
... where some-mysql is the name of your original mysql container
(connected to the some-network Docker network).
I started a mysql docker container, and then I tried to run another as the mysql client, but I don't know how to specific the --network parameter:
What should I input instead of some-network? I am newbie to Docker, and have no idea of Docker network. If I ommit this parameter, Unknown MySQL server host error is given.
Before you start the first container, you need to create a Docker network
docker network create some-network
You can use any name you want here, but I will use some-network for consistency with the question.
When you start the database container, it also needs to be attached to the same network
docker volume create mysql-data # this is essentially required too
docker run \
--name some-mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-d \
--net some-network \ # matches `docker network create`
-v mysql-data:/var/lib/mysql/data \ # don't lose data on restart
mysql:tag
(There is also a docker network connect command, but recreating containers to change settings is a pretty normal practice.)
You also don't need a second container to run a MySQL client: you can connect with the ordinary mysql command-line tool from the host. You need to publish a port out of the container
docker run \
-p 12345:3306 \
...
The first port number can be anything you want that doesn't conflict with another process on the host; the second number must be the standard MySQL port number 3306. You can then connect to that database with
mysql -h 127.0.0.1 -p 12345 -u example-user -p
Other answers to this question have endorsed Docker Compose as a setup. Compose will docker network create a network for you; Networking in Compose describes this setup in more detail. However, it's not great at running interactive terminal applications, and you might need to do something like docker-compose run db mysql -h db ... to get access to it this way. The published ports: approach will work too.
If you have more than one container which work together, you should read about docker-compose in order to config network, host, env var and so on...
// docker-compose.yml
version: "3.2"
services:
mysql_client:
depends_on:
- mysql_database
mysql_database:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: test
MYSQL_DATABASE: test
MYSQL_USER: test
MYSQL_PASSWORD: test
# exec this command to up your containers
docker-compose up
By default container are on the same network, in your mysql_client use mysql_database as hostname for mysql connection.
Via DockerHub I found this docker compose script to have Adminer and MySQL running in harmony.
# Use root/example as user/password credentials
version: '3.1'
services:
adminer:
image: adminer
restart: always
ports:
- 8080:8080
db:
image: mysql:5.6
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
Save it ti a file called docker-compose.yml and run it using docker-compose.
In cmd promt navigate to the directory containing the file and run the following:
docker-compose up
docker-compose reference

connection laravel with mysql container on docker

On Docker I already have a Laravel container and Container MySQL, how to connect the MySQL container and container Laravel on Docker?
This is what docker-compose was made for!
Check out this tutorial: https://docs.docker.com/compose/wordpress/
It's trying to do something similar: connect wordpress to mysql. The key is that both the docker containers defined in docker-compose.yml share the same network - and you can refer to each container by using their logical name. See how the WORDPRESS_DB_HOST environment variable is set to db:3306 - that will resolve to the IP of the mysql container within the docker network.
Basically, all containers must run in the same network.
# create your network
$ docker network create laravel
# start your container and link it to your network
$ docker run -d --network="laravel" --name="mysql01" mysql:8.0
# after your mysql is up and running, connect your second and third container like this
$ docker run -d --network="laravel" --name="latihananakit_web" yourimage:yourtag
$ docker run -d --network="laravel" --name="latihananakit_app" yourimage:yourtag
I'd recommend to use docker-compose for this scenario, because it makes the whole docker run-thing a lot easier.
See here for reference:
https://docs.docker.com/compose/
https://github.com/bitnami/bitnami-docker-laravel/blob/master/docker-compose.yml
TL;DR:
Create your docker-compose.yml like this (you may change environment-variables or other configuration upon your need):
version: '2'
services:
mariadb:
image: 'bitnami/mariadb:latest'
environment:
- ALLOW_EMPTY_PASSWORD=yes
- MARIADB_USER=my_user
- MARIADB_DATABASE=my_database
- MARIADB_PASSWORD=my_password
myapp:
tty: true
image: bitnami/laravel:5-debian-9
environment:
- DB_HOST=mariadb
- DB_USERNAME=my_user
- DB_DATABASE=my_database
- DB_PASSWORD=my_password
depends_on:
- mariadb
ports:
- 3000:3000
volumes:
- ./:/app
And get everything up and running by executing docker-compose up -d in the same directory.

mysql docker image support multiply databases creation at start

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.

docker-compose: seeing all the services together from command line

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.