mysql docker container : create database, user and execute commands automatically - mysql

I have followed this post create database and table automatically with docker-compose to execute a script at startup of my container.
The database is created and a user i defined in the docker-compose is created, my database is not populated like i have set in the sql script.
Can anyone help me?
here is the dockerfile:
FROM phpmyadmin
COPY DockerCreateAllTablesDBwithData.sql /docker-entrypoint-initdb.d/initdb.sql
Here is the docker-compose.yml:
---
version: '3.7'
services:
db:
image: mysql:8-debian
container_name: db
restart: always
networks:
- network_app
cap_add:
- SYS_NICE
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_USER=admin
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=CantineTest
- TZ='Europe/Paris'
volumes:
- mydatavolume:/var/lib/mysql
phpmyadmin:
build:
context: .
dockerfile: ./Dockerfile
container_name: phpmyadmin
restart: always
ports:
- 8080:80
depends_on:
- db
# volumes:
# - ./data/certbot/conf:/etc/letsencrypt
networks:
- network_app
environment:
- PMA_HOST=db
- TZ="Europe/Paris"
#volumes:
# frontendbuild:
# name: frontendbuild
networks:
network_app:
name: network_app
volumes:
mydatavolume:
And here is the DockerCreateAllTablesDBwithData.sql:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
--
-- Bdd : `CantineTest`
--
create database CantineTest;
use CantineTest;
DROP TABLE IF EXISTS `Alias`;
CREATE TABLE `Alias` (
`AliasID` smallint(5) UNSIGNED NOT NULL,
`AliasName` varchar(50) NOT NULL,
`AliasDescription` varchar(255) DEFAULT NULL,
`AliasMailingList` mediumtext NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

You have added the DB script to a wrong place. Must be added to the docker-composer where you have MySQL. Add as a volume
volumes:
- ./mysql-dump:/docker-entrypoint-initdb.d
Create a mysql-dump folder where you have docker-compose and add your SQL script to it.

Related

How to connect Node express server-docker-image to mysql docker image via digitalOcean droplet?

I have an experimental app where I am working with images. The goal is to make a full working app with docker containers and images which I have managed to do on my local machine. The issue im having is when im deploying it to digitalocean.
from the node-express-server im getting this error response:
{
"status": "error",
"statusCode": 500,
"message": {
"errno": "ENOTFOUND",
"code": "ENOTFOUND",
"syscall": "getaddrinfo",
"hostname": "dbcontainer",
"fatal": true
}
}
Im using docker-compose file:
services:
mysql:
build:
context: ./DbScripts
dockerfile: ./Dockerfile.prod
command:
- "--default-authentication-plugin=mysql_native_password"
container_name: dbcontainer
cap_add:
- SYS_NICE
ports:
- 3307:3306
restart: always
networks:
- mynetwork
environment:
MYSQL_DATABASE: todo
MYSQL_USER: produser
MYSQL_ROOT_PASSWORD: Password!
MYSQL_PASSWORD: Password!
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 1s
retries: 120
phpmyadmin:
# build: .
image: phpmyadmin/phpmyadmin
container_name: dev_pma
networks:
- mynetwork
environment:
PMA_HOST: dbcontainer
PMA_PORT: 3307
PMA_ARBITRARY: 1
restart: always
ports:
- 8183:80
server:
container_name: server
build:
context: ./BE
dockerfile: ./Dockerfile.prod
networks:
- mynetwork
ports:
- 4000:4000
client:
container_name: FE
build:
context: ./FE
dockerfile: ./Dockerfile.prod
networks:
- mynetwork
ports:
- 3000:3000
environment:
- CHOKIDAR_USEPOLLING=true
tty: true
volumes:
db_data:
networks:
mynetwork:
Im also using dockerfiles inside of the docker-compose. The releveant ones are:
mysql Dockerfile:
FROM mysql
ENV MYSQL_ROOT_PASSWORD Dsb2016!
ADD /DumpTodoOnly.sql /docker-entrypoint-initdb.d
EXPOSE 3306
Above im using a sql file to create database and user:
CREATE USER 'produser'#'localhost' IDENTIFIED WITH mysql_native_password BY 'Password!';
GRANT ALL PRIVILEGES ON *.* TO 'produser'#'localhost' WITH GRANT OPTION;
CREATE DATABASE IF NOT EXISTS `todo` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `todo`;
-- MySQL dump 10.13 Distrib 8.0.18, for Win64 (x86_64)
--
-- Host: localhost Database: todo
-- ------------------------------------------------------
-- Server version 8.0.18
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8 */;
/*!40103 SET #OLD_TIME_ZONE=##TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET #OLD_SQL_NOTES=##SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `todos`
--
DROP TABLE IF EXISTS `todos`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `todos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`todotext` varchar(200) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = #saved_cs_client */;
--
-- Table structure for table `users`
--
DROP TABLE IF EXISTS `users`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `users` (
`Id` varchar(36) NOT NULL,
`Email` varchar(200) NOT NULL,
`Password` binary(60) NOT NULL,
`ChangedPassword` bit(1) NOT NULL,
`FirstName` varchar(45) NOT NULL,
`LastName` varchar(45) NOT NULL,
`ImageId` varchar(36) DEFAULT NULL,
`SeqRef` varchar(36) DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `Email_UNIQUE` (`Email`),
UNIQUE KEY `Id_UNIQUE` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci KEY_BLOCK_SIZE=2;
/*!40101 SET character_set_client = #saved_cs_client */;
--
-- Dumping routines for database 'todo'
--
/*!40103 SET TIME_ZONE=#OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=#OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=#OLD_SQL_NOTES */;
-- Dump completed on 2022-04-12 0:18:13
The connection in my node express:
const connector = mysql.createPool({
connectionLimit: 20,
host: "dbcontainer",
database: "todo",
user: "produser",
password: "Password!",
});
Images
I run docker-compose up -d --build and get this:
I copy the imageId of the server, sql and php and for each of these I tag it :
docker tag imageId ghcr.io/userName/imageName:1
And push it to github packages:
docker push ghcr.io/userName/imageName:1
DigitalOcean
I connect to my github account and pull the images from github packages.
I run mysql image first and after doing that I enter the container to see if my database and user got created which I can verify that they have since both the Todo db and user "produser" are created on digitalOcean:
--------------------
| Database |
--------------------
| information_schema |
| mysql |
| performance_schema |
| sys |
| todo |
--------------------
------------------
| user |
------------------
| root |
| mysql.infoschema |
| mysql.session |
| mysql.sys |
| produser |
| root |
------------------
The containers on digitalocean look like this:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8fc8145a30c ghcr.io/username/phpnewest:1 "/docker-entrypoint.…" 10 minutes ago Up 10 minutes 0.0.0.0:8183->80/tcp, :::8183->80/tcp agitated_antonelli
dab65fd84ddb ghcr.io/username/serverlatest:1 "docker-entrypoint.s…" 11 minutes ago Up 11 minutes 0.0.0.0:4000->4000/tcp, :::4000->4000/tcp unruffled_goldberg
cc3fdf91e7ab dbcontainer "docker-entrypoint.s…" 13 minutes ago Up 13 minutes 33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp friendly_ardinghelli
Again everything worked on my machine but when pushing to digitalocean I get the server error above and on the phpAdmin I get:
mysqli::real_connect(): php_network_getaddresses: getaddrinfo failed:
Name or service not known mysqli::real_connect(): (HY000/2002):
php_network_getaddresses: getaddrinfo failed: Name or service not
known
Where have I gone wrong? Have I missed a configuration somewhere on the server?
Im running a droplet with Docker 19.03.12 on ubuntu.
Im new to docker-compose and as I said im building it and then tagging the images seperatly and pushing them, is this correct? Any guidence is appreciated.
EDIT:
Dont know how relevant this is but when I was inside of the dbcontainer I checked to see hon what host the mysql was running and it was "localhost".
Doing the same for the node-express with the following command:
docker exec -it serverid /bash/sh
And then hostname I just got back the container id.
EDIT2:
Maybe to ultral clear about this:
I run docker-compose on my local machine(my pc) only. Then I take each image seperatly and try to connect them on a droplet on digitalOceean.
I have also tried to change my docker-compose to this:
version: "3.7"
networks:
mynet:
volumes:
mysqldb_data:
phpmyadmin_data:
services:
mysql:
build:
context: ./DbScripts
dockerfile: ./Dockerfile.prod
command:
- "--default-authentication-plugin=mysql_native_password"
environment:
MYSQL_DATABASE: todo
MYSQL_USER: produser
MYSQL_ROOT_PASSWORD: Password!
MYSQL_PASSWORD: Password!
volumes:
- ./DbScripts/DumpTodoOnly.sql:/docker-entrypoint-initdb.d/DumpTodoOnly.sql
- mysqldb_data:/var/lib/mysql
networks:
- mynet
phpmyadmin:
image: phpmyadmin/phpmyadmin:fpm-alpine
environment:
PMA_HOST: mysql
volumes:
- phpmyadmin_data:/var/www/html/
networks:
- mynet
depends_on:
- mysql
ports:
- 8183:80
nginx:
image: nginx:1.17.4-alpine
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf:ro
- phpmyadmin_data:/var/www/html/:ro
ports:
- "90:80"
networks:
- mynet
depends_on:
- mysql
- phpmyadmin
Sadly this docker-compose attempt resulted in the php admin not working where I get connection_refused both on localhost and on the droplet.
the datbase and user still get created on the server and local machine.
The nginx did not run on local enviorment but did run on the droplet. Not sure what it should do in this scenario though.
For anyone attempting an ansewr please give me a step by step guide.
Right now I am doing the following:
Run docker-compose on local enviorment
Push each individual image to github packages
Connect to digitalOcean
Pull the images
Run each image on specific port.
My process must be obviosly faulty since it does not work.
After 2 weeks of trying I managed to get this spinning.
The core problem was that I did not quite understand the use of docker-compose. My intial thought was that the images it created could just be used as standalone and then they would autmactially link.
The solution is quite simple
I use this docker-compose:
services:
mysql:
build:
context: ./DbScripts
dockerfile: ./Dockerfile.prod
command:
- "--default-authentication-plugin=mysql_native_password"
container_name: dbcontainer
cap_add:
- SYS_NICE # CAP_SYS_NICE
ports:
- 3307:3306
restart: always
networks:
- mynetwork
environment:
MYSQL_DATABASE: todo
MYSQL_USER: produser
MYSQL_ROOT_PASSWORD: Password!
MYSQL_PASSWORD: Password!
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 1s
retries: 120
phpmyadmin:
# build: .
image: phpmyadmin/phpmyadmin
container_name: dev_pma
networks:
- mynetwork
environment:
PMA_HOST: dbcontainer
PMA_PORT: 3307
PMA_ARBITRARY: 1
restart: always
ports:
- 8183:80
server:
container_name: server
build:
context: ./BE
dockerfile: ./Dockerfile.prod
networks:
- mynetwork
ports:
- 4000:4000
client:
container_name: FE
build:
context: ./FE
dockerfile: ./Dockerfile.prod
networks:
- mynetwork
ports:
- 3000:3000
environment:
- CHOKIDAR_USEPOLLING=true
tty: true
volumes:
db_data:
networks:
mynetwork:
I list my images with docker image ls
I tag these images and push them to my github repo.
Now I create a new docker-compose file for production which refers to my finished images:
services:
mysql:
build: .
image: ghcr.io/githubusername/mysql:1
command:
- "--default-authentication-plugin=mysql_native_password"
container_name: dbcontainer
cap_add:
- SYS_NICE
ports:
- 3307:3306
restart: always
networks:
- mynetwork
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 1s
retries: 120
phpmyadmin:
build: .
image: ghcr.io/githubusername/php:1
container_name: dev_pma
networks:
- mynetwork
environment:
PMA_HOST: dbcontainer
PMA_PORT: 3307
PMA_ARBITRARY: 1
restart: always
ports:
- 8183:80
server:
container_name: server
build: .
image: ghcr.io/githubusername/server:1
networks:
- mynetwork
ports:
- 4000:4000
client:
build: .
image: ghcr.io/githubusername/client:1
container_name: FE
networks:
- mynetwork
ports:
- 3000:3000
environment:
- CHOKIDAR_USEPOLLING=true
tty: true
volumes:
db_data:
networks:
mynetwork:
Now this is basically where the magic happened:
Once inside of DigitalOcean droplet I created a docker-compose file by nano docker.compose.yml
I add the contents of the production file inside and on the droplet I run docker-compose up
Now I can not say how optimal all of this is at this moment more than you should not show your enviorment variables directly in the docker-compose file but It works.

How can I initialize a database with some tables in a container using docker compose?

I have my db service:
...
mysql-server:
container_name: silos-database
init: true
restart: always
build:
context: .
dockerfile: Dockerfile-db
environment:
- MYSQL_ROOT_PASSWORD=${ROOT_PASSWORD}
- MYSQL_DATABASE=${DATABASE}
- MYSQL_USER=${USER}
- MYSQL_PASSWORD=${USER_PASSWORD}
ports:
- target: 3036
published: 3036
networks:
- backend-net
volumes:
- type: volume
source: db_vol
target: /var/lib/mysql
...
This is my Dockerfile
FROM mysql:latest
The init.sql file contain same tables that my database must have
...
-- users data
CREATE TABLE IF NOT EXISTS users (
email VARCHAR(128) PRIMARY KEY,
username VARCHAR(64) UNIQUE,
-- password is SHA256 hashed, so 64 characters
password CHAR(64) NOT NULL
);
CREATE TABLE IF NOT EXISTS sessions (
email VARCHAR(128) PRIMARY KEY,
token TEXT NOT NULL,
expireDate BIGINT(13) NOT NULL,
FOREIGN KEY (email) REFERENCES users(email) ON UPDATE CASCADE ON DELETE CASCADE
);
...
How can I build a service with the content of init.sql file already inside the service?
The simplest way would be to add init.sql file to Your docker image:
FROM mysql:latest
ADD init.sql /docker-entrypoint-initdb.d
If You want to provide init.sql during container start instead of build time, You can mount directory containing init.sql into container:
mysql-server:
container_name: silos-database
init: true
restart: always
build:
context: .
dockerfile: Dockerfile-db
environment:
- MYSQL_ROOT_PASSWORD=${ROOT_PASSWORD}
- MYSQL_DATABASE=${DATABASE}
- MYSQL_USER=${USER}
- MYSQL_PASSWORD=${USER_PASSWORD}
ports:
- target: 3036
published: 3036
networks:
- backend-net
volumes:
- type: volume
source: db_vol
target: /var/lib/mysql
- /local/path/with/initsql:/docker-entrypoint-initdb.d

Connection failed to dockarized MySQL service

I have dockarized MySQL container running. When I try to connect to this mysql-docker-service from other dockarized applications, it fails.
My docker-compose :
version: '3'
services:
mysqlserver:
image: mysql-server
container_name: mysqlcontainer
build:
context: mysql-module/
dockerfile: Dockerfile
env_file: mysql-module/mysql.env
networks:
- backend
volumes:
- ./mysql-data:/var/lib/mysql
ports:
- 8001:3306
users:
image: users
build:
context: .
dockerfile: Dockerfile
ports:
- 7171:7171
env_file: ./api.env
networks:
- backend
networks:
backend:
driver: "bridge"
MySQL dockerfile :
FROM mysql/mysql-server:latest
ENV MYSQL_DATABASE userservice
ADD sql-scripts/createUsers.sql /docker-entrypoint-initdb.d
I get database credentials from external file.
MYSQLDBGATEWAY=root:7890#tcp(mysqlcontainer://mysqlserver:8001)/userservice?parseTime=true
Error getting user details dial tcp: lookup mysqlcontainer://mysqlserver:8001: no such host
What am I missing here? This is my first dockerized MySQL work.
Also in sql-scripts/createUsers.sql file I have :
CREATE TABLE IF NOT EXISTS managerMinQuota (
id int NOT NULL AUTO_INCREMENT,
plan varchar(50) DEFAULT NULL,
minLimit int DEFAULT NULL,
PRIMARY KEY (id)
);
But this is not created at run time.

Partially executed init.sql

I am setting up a dev environment based on docker-compose for a simple tool that needs just a table with a few columns. I can successfully build the image with the followting docker-compose.yml file.
services:
# [main service...]
mysql:
image: mysql:latest
container_name: feedback_db
volumes:
- "./init_db.sql:/docker-entrypoint-initdb.d/init_db.sql"
- "./mysql:/var/lib/mysql"
environment:
- MYSQL_ROOT_PASSWORD=testing
- MYSQL_DATABASE=feedback
- MYSQL_USER=db_user
- MYSQL_PASSWORD=password
ports:
- '3306:3306'
expose:
- '3306'
restart: on-failure
network_mode: host
volumes:
mysql:
Using the following init_db.sql commands:
-- create db if missing
CREATE DATABASE IF NOT EXISTS feedback;
-- create table
USE feedback;
CREATE TABLE user_feedback (
id INT NOT NULL AUTO_INCREMENT,
session_id VARCHAR(250),
ts TIMESTAMP,
content VARCHAR(250),
feedback VARCHAR(250),
PRIMARY KEY (id)
);
Now, everything gets built perrfectly and although the db gets created as per the init commands, the table creation part doesn't gets executed. The command works perfectly when executed manually inside the container.
I managed to solve the problem, writing an answer here as it might be helpful for other people with similar problem.
As #David correctly spotted, init_db.sql wasn't getting executed at all as docker-entrypoint-initdb.d expects to be mapped to a folder and not to a specific file as I was doing.
Putting init_db.sql file into a ./ìnit_db folder gets the job done:
mysql:
image: mysql:latest
container_name: feedback_db
command: mysqld --default-authentication-plugin=mysql_native_password
volumes:
- "./dev/init_db:/docker-entrypoint-initdb.d" # change: map to folder
- "./mysql:/var/lib/mysql"
environment:
- MYSQL_ROOT_PASSWORD=testing
- MYSQL_DATABASE=feedback
- MYSQL_USER=db_user
- MYSQL_PASSWORD=password
ports:
- '3306:3306'
expose:
- '3306'
restart: on-failure
network_mode: host
There's no need to create the database in my init_db.sql file as that will be taken care of by docker-compose. init_db.sql can be reworked into:
-- create table
USE feedback;
CREATE TABLE IF NOT EXISTS user_feedback (
id INT NOT NULL AUTO_INCREMENT,
session_id VARCHAR(250),
ts TIMESTAMP,
content VARCHAR(250),
feedback VARCHAR(250),
PRIMARY KEY (id)
);

Cannot access to mysql container from another container

I use docker compose to run mysql and api server. Once api server is on it use connect to mysql, but I always got a access denied. I have add sql to grant permission but it still not work. Please someone help me.
Error
2018-05-03T05:48:45.868146Z 2 [Note] Access denied for user 'mysql'#'172.18.0.3' (using password: YES)
Here is my docker-compose
version: "3.6"
services:
mysql:
build:
context: ..
dockerfile: docker/Dockerfile-mysql
image: test_mysql:ci-label
container_name: test-mysql-ci-label
labels:
- "CI-TEST=ci-label"
networks:
- ci-network
ports:
- "3306:3306"
license:
build:
context: ..
dockerfile: docker/Dockerfile
image: test_license:ci-label
container_name: test-license-ci-label
environment:
- NODE_ENV=dockertest
- PORT=9502
labels:
- "CI-TEST=ci-label"
networks:
- ci-network
ports:
- "9502:9502"
depends_on:
- mysql
privileged: true
networks:
ci-network:
labels:
- "CI-TEST=ci-label"
name: ci-network
Here is my Dockerfile-mysql
FROM mysql:5.7
LABEL CI-TEST="ci-label"
ENV MYSQL_ALLOW_EMPTY_PASSWORD=yes
MYSQL_USER=mysql \
MYSQL_PASSWORD=test
COPY init.sql docker-entrypoint-initdb.d/01.sql
Here is init.sql
-- Create database.
CREATE SCHEMA IF NOT EXISTS `license` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
-- Create new user.
GRANT ALL PRIVILEGES ON license.* TO 'mysql'#'%' IDENTIFIED BY 'test';
GRANT ALL PRIVILEGES ON license.* TO 'mysql'#'localhost' IDENTIFIED BY 'test';
FLUSH PRIVILEGES;