Bir MySQL veritabanını Docker konteynerinde şema ile nasıl başlatabilirim?

MySQL veritabanı ile bir konteyner oluşturmaya ve bu veritabanına bir şema eklemeye çalışıyorum.

Şu anki Docker dosyam:

FROM mysql
MAINTAINER  (me) <email>

# Copy the database schema to the /data directory
COPY files/epcis_schema.sql /data/epcis_schema.sql

# Change the working directory
WORKDIR data

CMD mysql -u $MYSQL_USER -p $MYSQL_PASSWORD $MYSQL_DATABASE < epcis_schema.sql

Konteyneri oluşturmak için Docker'da sağlanan belgeleri takip ediyorum ve bu komutu çalıştırıyorum:

docker run --name ${CONTAINER_NAME} -e MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} -e MYSQL_USER=${DB_USER} -e MYSQL_PASSWORD=${DB_USER_PASSWORD} -e MYSQL_DATABASE=${DB_NAME} -d mvpgomes/epcisdb

Ancak bu komutu çalıştırdığımda Konteyner oluşturulmuyor ve Konteyner durumunda CMD'nin başarılı bir şekilde yürütülmediğini görmek mümkün, aslında sadece mysql komutu yürütülüyor.

Her neyse, veritabanını şema ile başlatmanın bir yolu var mı yoksa bu işlemleri manuel olarak mı yapmam gerekiyor?

Çözüm

Bu çok uzun cevap için özür dilerim, ancak istediğiniz yere ulaşmak için biraz yolunuz var. Normalde veritabanı için depolama alanını veritabanının kendisiyle aynı konteynere koymayacağınızı söyleyeceğim, ya bir ana bilgisayar birimi bağlarsınız, böylece veriler docker ana bilgisayarında kalır ya da belki verileri tutmak için bir konteyner kullanılabilir (/var/lib/mysql). Ayrıca, mysql'de yeniyim, bu yüzden bu süper verimli olmayabilir. Bununla birlikte...

Sanırım burada birkaç sorun olabilir. Dockerfile bir imaj oluşturmak için kullanılır. Derleme adımını çalıştırmanız gerekir. En azından, Dockerfile'ı içeren dizinden şöyle bir şey yapmalısınız:

docker build .

Dockerfile oluşturulacak görüntüyü tanımlıyor. Mysql hakkında çok fazla bilgim yok (ben bir postgres fanboyuyum), ama internette 'bir mysql docker konteynerini nasıl başlatırım' diye bir arama yaptım. Önce çalışmak için yeni bir dizin oluşturdum, buna mdir adını verdim, sonra bir veritabanı ve tek bir tablo oluşturan bir epcis_schema.sql dosyasını bıraktığım bir dosyalar dizini oluşturdum:

create database test;
use test;

CREATE TABLE testtab
(
id INTEGER AUTO_INCREMENT,
name TEXT,
PRIMARY KEY (id)
) COMMENT='this is my test table';

Daha sonra dosyalar dizininde init_db adında bir betik oluşturdum:

#!/bin/bash

# Initialize MySQL database.
# ADD this file into the container via Dockerfile.
# Assuming you specify a VOLUME ["/var/lib/mysql"] or `-v /var/lib/mysql` on the `docker run` command…
# Once built, do e.g. `docker run your_image /path/to/docker-mysql-initialize.sh`
# Again, make sure MySQL is persisting data outside the container for this to have any effect.

set -e
set -x

mysql_install_db

# Start the MySQL daemon in the background.
/usr/sbin/mysqld &
mysql_pid=$!

until mysqladmin ping >/dev/null 2>&1; do
  echo -n "."; sleep 0.2
done

# Permit root login without password from outside container.
mysql -e "GRANT ALL ON *.* TO root@'%' IDENTIFIED BY '' WITH GRANT OPTION"

# create the default database from the ADDed file.
mysql < /tmp/epcis_schema.sql

# Tell the MySQL daemon to shutdown.
mysqladmin shutdown

# Wait for the MySQL daemon to exit.
wait $mysql_pid

# create a tar file with the database as it currently exists
tar czvf default_mysql.tar.gz /var/lib/mysql

# the tarfile contains the initialized state of the database.
# when the container is started, if the database is empty (/var/lib/mysql)
# then it is unpacked from default_mysql.tar.gz from
# the ENTRYPOINT /tmp/run_db script

(bu senaryonun çoğu buradan alınmıştır: https://gist.github.com/pda/9697520)

İşte oluşturduğum files/run_db betiği:

# start db

set -e
set -x

# first, if the /var/lib/mysql directory is empty, unpack it from our predefined db
[ "$(ls -A /var/lib/mysql)" ] && echo "Running with existing database in /var/lib/mysql" || ( echo 'Populate initial db'; tar xpzvf default_mysql.tar.gz )

/usr/sbin/mysqld

Son olarak, hepsini bağlamak için Docker dosyası:

FROM mysql
MAINTAINER  (me) 

# Copy the database schema to the /data directory
ADD files/run_db files/init_db files/epcis_schema.sql /tmp/

# init_db will create the default
# database from epcis_schema.sql, then
# stop mysqld, and finally copy the /var/lib/mysql directory
# to default_mysql_db.tar.gz
RUN /tmp/init_db

# run_db starts mysqld, but first it checks
# to see if the /var/lib/mysql directory is empty, if
# it is it is seeded with default_mysql_db.tar.gz before
# the mysql is fired up

ENTRYPOINT "/tmp/run_db"

Bu yüzden, mdir dizinime (dosyalar dizini ile birlikte Docker dosyasını içeren) cd'ledim. Daha sonra şu komutu çalıştırdım:

docker build --no-cache .

Bunun gibi bir çıktı görmelisiniz:

Sending build context to Docker daemon 7.168 kB
Sending build context to Docker daemon 
Step 0 : FROM mysql
 ---> 461d07d927e6
Step 1 : MAINTAINER (me) 
 ---> Running in 963e8de55299
 ---> 2fd67c825c34
Removing intermediate container 963e8de55299
Step 2 : ADD files/run_db files/init_db files/epcis_schema.sql /tmp/
 ---> 81871189374b
Removing intermediate container 3221afd8695a
Step 3 : RUN /tmp/init_db
 ---> Running in 8dbdf74b2a79
+ mysql_install_db
2015-03-19 16:40:39 12 [Note] InnoDB: Using atomics to ref count buffer pool pages
...
/var/lib/mysql/ib_logfile0
 ---> 885ec2f1a7d5
Removing intermediate container 8dbdf74b2a79
Step 4 : ENTRYPOINT "/tmp/run_db"
 ---> Running in 717ed52ba665
 ---> 7f6d5215fe8d
Removing intermediate container 717ed52ba665
Successfully built 7f6d5215fe8d

Artık bir görüntünüz var '7f6d5215fe8d'. Bu görüntüyü çalıştırabilirim:

docker run -d 7f6d5215fe8d

ve görüntü başladığında bir örnek dizesi görüyorum:

4b377ac7397ff5880bc9218abe6d7eadd49505d50efb5063d6fab796ee157bd3

Daha sonra 'durdurabilir' ve yeniden başlatabilirim.

docker stop 4b377
docker start 4b377

Günlüklere bakarsanız, ilk satır şunları içerecektir:

docker logs 4b377

Populate initial db
var/lib/mysql/
...

Sonra, kayıtların sonunda:

Running with existing database in /var/lib/mysql

Bunlar /tmp/run_db betiğinden gelen mesajlardır, ilki veritabanının kaydedilmiş (ilk) sürümden açıldığını gösterir, ikincisi ise veritabanının zaten orada olduğunu, bu nedenle mevcut kopyanın kullanıldığını gösterir.

İşte yukarıda tanımladığım dizin yapısının ls -lR'si. init_db ve run_db'nin execute biti ayarlanmış betikler olduğuna dikkat edin:

gregs-air:~ gfausak$ ls -Rl mdir
total 8
-rw-r--r--  1 gfausak  wheel  534 Mar 19 11:13 Dockerfile
drwxr-xr-x  5 gfausak  staff  170 Mar 19 11:24 files

mdir/files:
total 24
-rw-r--r--  1 gfausak  staff   126 Mar 19 11:14 epcis_schema.sql
-rwxr-xr-x  1 gfausak  staff  1226 Mar 19 11:16 init_db
-rwxr-xr-x  1 gfausak  staff   284 Mar 19 11:23 run_db
Yorumlar (10)

Greg'in cevabını sıfır başarı ile denedim, tüm adımlardan sonra veritabanımda veri olmadığına göre bir şeyleri yanlış yapmış olmalıyım: Her ihtimale karşı MariaDB'nin en son sürümünü kullanıyordum.

Daha sonra resmi MariaDB imajı giriş noktasını okumaya karar verdim ve bunu basit bir docker-compose dosyası oluşturmak için kullandım:

database:
  image: mariadb
  ports:
     - 3306:3306
  expose:
     - 3306
  volumes:
     - ./docker/mariadb/data:/var/lib/mysql:rw
     - ./database/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
  environment:
     MYSQL_ALLOW_EMPTY_PASSWORD: "yes"

Artık verilerimi kalıcı hale getirebiliyorum VE kendi şemamla bir veritabanı oluşturabiliyorum!

Yorumlar (2)

En kolay çözüm tutum/mysql kullanmaktır.

Adım1

docker pull tutum/mysql:5.5

Adım2

docker run -d -p 3306:3306 -v /tmp:/tmp  -e STARTUP_SQL="/tmp/to_be_imported.mysql" tutum/mysql:5.5

Adım3

Yukarıdaki CONTAINER_ID'yi alın ve ardından oluşturulan parola bilgilerini görmek için docker logs komutunu çalıştırın.

docker logs #
Yorumlar (6)