Bir Docker kapsayıcısında şema içeren bir MySQL veritabanını nasıl başlatabilirim?


167

Bir MySQL veritabanı ile bir kap oluşturmak ve bu veritabanına bir şema eklemek ç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

Kapsayıcı oluşturmak için Docker'da sağlanan belgeleri izliyorum ve bu komutu yürütü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 yürüttüğümde Container oluşturulmaz ve Container durumunda CMD'nin başarıyla yürütülmediğini görmek mümkündür, aslında sadece mysqlkomut yürütülür.

Her neyse, veritabanını şema ile başlatmanın bir yolu var mı veya bu işlemleri el ile yapmam gerekiyor mu?


i tohumlanmış ve gitmeye hazır bir veritabanı ile yeni bir görüntü oluşturmak istediğinizi varsayalım?
Greg

Evet, tam olarak bunu yapmak istiyorum.
Marcus Gomes


Burada da açıklanmıştır: medium.com/@lvthillo/…
lvthillo

Yanıtlar:


105

Bu süper uzun cevap için özür dilerim, ama istediğiniz yere ulaşmak için küçük bir yolunuz var. Normalde veritabanı için depolama alanını veritabanının kendisiyle aynı kaba koymayacağınızı, verilerin bir docker ana bilgisayarında kalması için bir ana bilgisayar birimi bağlayacağınızı veya belki de bir kapın verileri tutun (/ var / lib / mysql). Ayrıca, ben mysql için yeniyim, bu yüzden, bu süper verimli olmayabilir. Bahsedilen...

Burada birkaç sorun olabileceğini düşünüyorum. Dockerfile bir görüntü oluşturmak için kullanılır. Derleme adımını yürütmeniz gerekir. En azından Dockerfile dosyasını içeren dizinden şöyle bir şey yaparsınız:

docker build .

Dockerfile oluşturulacak görüntüyü açıklar. MySQL hakkında çok şey bilmiyorum (ben bir postgres fanboy), ama, 'nasıl bir mysql docker konteyner başlatmak nasıl' için interwebs etrafında 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ı bıraktığım bir dosya 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';

Sonra dosya dizininde init_db adlı bir komut dosyası 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 komut dosyasının çoğu buradan kaldırıldı: https://gist.github.com/pda/9697520 )

Oluşturduğum dosyalar / 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, Dockerfile hepsini bağlamak için:

FROM mysql
MAINTAINER  (me) <email>

# 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 (dosya diziniyle birlikte Dockerfile içeren) cd'ed'im. Sonra komutu çalıştırın:

docker build --no-cache .

Aşağıdaki 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) <email>
 ---> 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

Şimdi bir resminiz var '7f6d5215fe8d'. Bu resmi çalıştırabilirim:

docker run -d 7f6d5215fe8d

ve görüntü başlar, bir örnek dize görüyorum:

4b377ac7397ff5880bc9218abe6d7eadd49505d50efb5063d6fab796ee157bd3

Sonra 'durdurabilirim' ve yeniden başlatabilirim.

docker stop 4b377
docker start 4b377

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

docker logs 4b377

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

Sonra, günlüklerin sonunda:

Running with existing database in /var/lib/mysql

Bunlar / tmp / run_db komut dosyasındaki iletilerdir, ilki veritabanının kaydedilmiş (ilk) sürümden açıldığını gösterir, ikincisi veritabanının zaten orada olduğunu gösterir, bu nedenle mevcut kopya kullanıldı.

Yukarıda açıkladığım dizin yapısının bir ls -lR'si. İnit_db ve run_db komutlarının yürütme biti ayarlanmış komut dosyaları 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

3
Hey Gary, önce bana yardım ettiğin için teşekkürler. Talimatlarınıza uydum, ancak docker build --no-cache komutunu çalıştırdığımda. , init_dbKomut dosyası için izin hatası var .
Marcus Gomes

Zaten RUNkomut izinleri vererek düzeltmeye çalışın ve sorun görünüşte çözüldü. Ama sonra yürüttüğümde senaryo docker runile aynı sorunu yaşıyorum run_db.
Marcus Gomes

1
init_db ve run_db'nin 0755 izni olması gerekir (komut dosyalarıdır, yürütme biti ayarlanmalıdır. chmod + x init_db run_db
Greg

Cevabı, dosyaların her birindeki izinleri gösteren bir dizin listesiyle güncelledim. Not: chmod + x dosyaları / * _ db gereken izinleri yerine getirecektir.
Greg

2
@Greg Yukarıdaki adımları denedim ancak bir hata alıyorum ([HATA] Önemli hata: Kök olarak mysqld nasıl çalıştırılacağını öğrenmek için lütfen kılavuzun "Güvenlik" bölümünü okuyun!) Baska öneri ?
Binish John

123

MySQL Docker örneğimin şemasını başlatmak istediğim aynı sorunu yaşadım, ancak bazı Googling yaptıktan ve başkalarının örneklerini izledikten sonra bu çalışmayı elde etmekte zorlandım. İşte böyle çözdüm.

1) MySQL şemanızı bir dosyaya dökün.

mysqldump -h <your_mysql_host> -u <user_name> -p --no-data <schema_name> > schema.sql

2) Şema dosyanızı /docker-entrypoint-initdb.dDocker kapsayıcısındaki dizine eklemek için ADD komutunu kullanın . docker-entrypoint.shDosya ile biten bu dizindeki tüm dosyaları çalışır ".sql"MySQL veritabanıyla.

Dockerfile:

FROM mysql:5.7.15

MAINTAINER me

ENV MYSQL_DATABASE=<schema_name> \
    MYSQL_ROOT_PASSWORD=<password>

ADD schema.sql /docker-entrypoint-initdb.d

EXPOSE 3306

3) Docker MySQL örneğini başlatın.

docker-compose build
docker-compose up

Sayesinde MySQL kurma ve Dockerfile içinde dökümü ithal docker-entrypoint.sh ve hem SQL ve kabuk komut dosyaları çalışır gerçeğine beni clueing için!


2
Bu kesinlikle daha iyi cevap. DDL'leri ve başlatma komut dosyalarını /docker-entrypoint-initdb.d dizinine kopyalamak, dockerhub mysql belgelerinin bu tür şeylerle ne yaptığını söyler.
chacewells

2
Bir şey değiştiğinde ne olur schema.sql? Benim db buna göre güncellenmesini istiyorum. Ayrıca bu kapsayıcıyı ikinci kez oluşturduğumda ne olur? Db imha edilecek mi ve yeniden yaratılacak mı?
Goga Koreli

1
@Goga Koreli Docker bu init komutunu yalnızca / var / lib / mysql
medTech

38

Daha önce burada verilen servis yanıtlarının birleştirilmesine dayanan başka bir yol:

docker-compose dosyası:

version: "3"
services:
    db:
      container_name: db
      image: mysql
      ports:
       - "3306:3306"  
      environment:
         - MYSQL_ROOT_PASSWORD=mysql
         - MYSQL_DATABASE=db

      volumes:
         - /home/user/db/mysql/data:/var/lib/mysql
         - /home/user/db/mysql/init:/docker-entrypoint-initdb.d/:ro

burada /home/user.. ana bilgisayarda paylaşılan bir klasördür

Ve /home/user/db/mysql/initklasörde .. herhangi bir adla bir sql dosyası bırakın, örneğin init.sql:

CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'%' IDENTIFIED BY 'mysql';
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost' IDENTIFIED BY 'mysql';
USE mydb
CREATE TABLE CONTACTS (
    [ ... ]
);
INSERT INTO CONTACTS VALUES ...
[ ... ]

Göre resmi MySQL belgelerinde , içeri birden fazla sql dosyasını koyabilirsiniz docker-entrypoint-initdb.d, alfabetik sırayla yürütülür


28

Diğer basit yol, docker-compose komutunu aşağıdaki satırlarla kullanın:

mysql:
  from: mysql:5.7
  volumes:
    - ./database:/tmp/database
  command: mysqld --init-file="/tmp/database/install_db.sql"

Veritabanı şemanızı ./database/install_db.sql dosyasına koyun. Kapsayıcısını her oluşturduğunuzda install_db.sql yürütülür.


26

Greg'in cevabını sıfır başarı ile denedim, veritabanımın tüm adımlardan sonra veri olmadığı için yanlış bir şey yapmalıydım: Her ihtimale karşı MariaDB'nin en son görüntüsünü kullanıyordum.

Sonra resmi MariaDB görüntüsü için 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"

Şimdi verilerimi saklayabiliyorum ve kendi şemayla bir veritabanı oluşturabiliyorum!


1
Merhaba, ben de aynısını yapmaya çalışıyorum, ama script asla yürütülmez. Sağlanması gereken başka bir parametre var mı? Bu birimi mariadb - ./database/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro için ekledim. Teşekkürler
bilak

Not: komut dosyası, konteyner başlatma sırasında yalnızca bir kez yürütülür. Daha sonra yeni bir komut dosyası eklerseniz çalıştırılmaz.
ALex_hha


11

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

Aşama 1

docker pull tutum/mysql:5.5

Adım 2

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

Aşama 3

CONTAINER_ID değerinin üstüne çıkın ve docker logsoluşturulan şifre bilgilerini görmek için komutu yürütün .

docker logs #<CONTAINER_ID>

Bunu başarıyla çalıştırmak için aldın mı? Başarısız bir şekilde haftalardır tutum / mysql ile uğraşıyorum.
Iammesol

2
Evet. Kullandığım tutum/mysql:5.5ve onu successed. docker run -d -p 3306:3306 -v /tmp:/tmp -e MYSQL_PASS="admin" -e STARTUP_SQL="/tmp/mysqldump.mysql" tutum/mysql:5.5. Sorunla docker logs CONTAINER_IDkarşılaşırsanız hata mesajlarını görmek için her zaman komutu yürütebilirsiniz .
mainframer

yolun nereden /tmp/to_be_imported.mysqlgeldiğini anlayamıyorum. bu ana bilgisayar işletim sistemindeki bir yol mu? nerede COPYveya bir ADDşeyleri kabın dosya sistemine yerleştirmek için?
Randy L

COPY/ the ADD/ tmp ana dizinine kapsayıcısının / tmp dizinine bağlı olduğunuz için @ . Komuta yakından bakın, kısım var -v /tmp:/tmp. Şahsen dosyayı kap için kullanılabilir hale getirmek için bir birim monte etmezdim ama sanırım kişisel bir seçim.
Willa

1
Adil olmak gerekirse, resmi olmayan görüntüleri kullanmamalısınız, istemiyorsanız bu daha olmasını.
Dragas

3

Benim gibi bir giriş noktası komut dosyası oluşturmak istemeyenler için, aslında mysqld'ı derleme zamanında başlatabilir ve Dockerfile'ınızda mysql komutlarını şu şekilde yürütebilirsiniz:

RUN mysqld_safe & until mysqladmin ping; do sleep 1; done && \
    mysql -uroot -e "CREATE DATABASE somedb;" && \
    mysql -uroot -e "CREATE USER 'someuser'@'localhost' IDENTIFIED BY 'somepassword';" && \
    mysql -uroot -e "GRANT ALL PRIVILEGES ON somedb.* TO 'someuser'@'localhost';"

Buradaki anahtar, mysqld_safe'yi tek &işaretli arka plana göndermek .


1

Aşağıda xampp'i yüklemek, şemayla bir MariaDB oluşturmak ve yerel sunucuda kullanılan bilgilerle (usrs, resim siparişleri, vb.) Önceden doldurduğum Dockerfile.

FROM ubuntu:14.04

COPY Ecommerce.sql /root

RUN apt-get update \
 && apt-get install wget -yq \
 && apt-get install nano \
 && wget https://www.apachefriends.org/xampp-files/7.1.11/xampp-linux-x64-7.1.11-0-installer.run \
 && mv xampp-linux-x64-7.1.11-0-installer.run /opt/ \
 && cd /opt/ \
 && chmod +x xampp-linux-x64-7.1.11-0-installer.run \
 && printf 'y\n\y\n\r\n\y\n\r\n' | ./xampp-linux-x64-7.1.11-0-installer.run \
 && cd /opt/lampp/bin \
 && /opt/lampp/lampp start \
 && sleep 5s \

 && ./mysql -uroot -e "CREATE DATABASE Ecommerce" \
 && ./mysql -uroot -D Ecommerce < /root/Ecommerce.sql \
 && cd / \
 && /opt/lampp/lampp reload \
 && mkdir opt/lampp/htdocs/Ecommerce

COPY /Ecommerce /opt/lampp/htdocs/Ecommerce

EXPOSE 80

0

Bununla biraz mücadele ettikten sonra, adlandırılmış birimleri (db-data) kullanarak Dockerfile'a bakın. Son bölümde bir artı beyan etmek önemlidir, burada hacmin[external]

Hepsi bu şekilde harika çalıştı!

version: "3"

services:

  database:
    image: mysql:5.7
    container_name: mysql
    ports:
      - "3306:3306"
    volumes:
      - db-data:/docker-entrypoint-initdb.d
    environment:
      - MYSQL_DATABASE=sample
      - MYSQL_ROOT_PASSWORD=root

volumes:
  db-data:
    external: true
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.