Partially executed init.sql - mysql

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

Related

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

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.

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.

Docker compose Mysql

i tried to do 2 changes on my docker-compose, but i'm didn't find how to do it.
1- I want to create 2 users.
2- I want to import a sql file from docker-compose.
version: '3.8'
services:
mysql:
image: mysql:8.0.21
command: --default-authentication-plugin=mysql_native_password
restart: always
container_name: mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER="user, user2"
- MYSQL_PASSWORD="pass, pass2"
- MYSQL_DATABASE=templateProject
- MYSQL_MAX_ALLOWED_PACKET=1024M
- MYSQL_INNODB_BUFFER_POOL_SIZE=1G
- MYSQL_INNODB_LOG_FILE_SIZE=256M
- MYSQL_INNODB_LOG_BUFFER_SIZE=256M
ports:
- '3361:3360'
volumes:
- ./dump.sql:/my_dump.sql
phpmyadmin:
image: phpmyadmin
restart: always
container_name: phpmyadmin
ports:
- 8080:80
environment:
- PMA_ARBITRARY=1
For #2 you should bind mount the directory containing your sql file like this:
"./folderwithsql:/docker-entrypoint-initdb.d"
For #1 You may be able to include another sql file in your "folderwithsql" mount that includes SQL statements to create the extra user. The file would contain something similar to these:
CREATE USER 'extrauser'#'%' IDENTIFIED BY 'passwordforextrauser';
GRANT INSERT, UPDATE, SELECT, DELETE ON mynewdb.* TO 'extrauser'#'%';

Restart Docker Compose with update to database

I've been working with a simple MySQL table using Docker Compose that only included ID and NAME column. I attempted to update my myDb.sql file that initially creates the table like this:
CREATE TABLE `Person` (
`id` int(11) NOT NULL,
`firstName` varchar(50) NOT NULL, // updated this column
`lastName` varchar(50) NOT NULL // added this column
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I updated the NAME column to firstName, and added a lastName column.
I then stopped the Docker containers by running DOCKER-COMPOSE STOP.
I then restarted the Docker containers by running DOCKER-COMPOSE UP. I even tried DOCKER-COMPOSE RESTART.
The error message I was able to print in the console was this:
SELECT '', id, `firstName` From Person<br>Unknown column 'firstName' in 'field list'
This leads me to believe that I did not restart Docker Compose correctly.
How do I restart Docker Compose so that it runs the CREATE TABLE command?
Edit
Here is my docker-compose.yml file:
version: "3.7"
services:
www:
build: .
ports:
- "8001:80"
volumes:
- ./www:/var/www/html/
links:
- db
networks:
- default
db:
image: mysql:5.7.13
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: myDb
MYSQL_USER: user
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
volumes:
- ./dump:/docker-entrypoint-initdb.d
- persistent:/var/lib/mysql
networks:
- default
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- db:db
ports:
- 8000:80
environment:
MYSQL_USER: user
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
volumes:
persistent:
My Dockerfile looks like this:
FROM php:7.0.30-apache
RUN docker-php-ext-install mysqli
The docker-entrypoint-initdb.d mechanism only runs the first time a database container starts up, with an empty database. You'll need to explicitly docker-compose rm your containers after you docker-compose stop them to cause the current database to be deleted, and then a new empty table will be created in a new empty database.
If you need to preserve the data in an existing database, you are looking for a mechanism called a migration. The various Docker database images don't directly have migration support; this is almost always something that is packaged with your application-level database library (Ruby on Rails and Python's SQLAlchemy both have migration facilities, for instance).
Once you have a migration system anyways, it's probably better to just use that to create the initial database tables. docker-entrypoint-initdb.d makes a little more sense for database-level setup like creating initial users or loading a seed database dump, but in practice you will always need a migration system for changes like what you're describing.
Do docker-compose down whenever you update your schema, it will remove containers and docker network and do docker-compose up to bring your environment with your new schema. Hope it helps. If not, try updating to latest mysql image, the image you are using is almost 3 years old.
So I was thinking that restarting docker-compose would automatically run the CREATE TABLE query in the myDb.sql file. As indicated above, I changed the name of 'name' column to 'firstName' and added a column called 'lastName'.
Again, I am not sure if there was a command that actually does this, but in the end, I was able to alter the table in phpmyadmin. Once I altered the table there, now I am getting data back to the page with no errors.