MySQL की स्थापना और Dockerfile के भीतर डंप आयात करता है


127

मैं अपने LAMP प्रोजेक्ट के लिए Dockerfile सेटअप करने का प्रयास कर रहा हूं, लेकिन MySQL शुरू करते समय मुझे कुछ समस्याएं हो रही हैं। मेरे पास मेरे डॉकरीफ़ाइल पर फ़ोलोइंग लाइनें हैं:

VOLUME ["/etc/mysql", "/var/lib/mysql"]
ADD dump.sql /tmp/dump.sql
RUN /usr/bin/mysqld_safe & sleep 5s
RUN mysql -u root -e "CREATE DATABASE mydb"
RUN mysql -u root mydb < /tmp/dump.sql

लेकिन मुझे यह त्रुटि मिलती रहती है:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)

कैसे एक Dockerfile बिल्ड के दौरान डेटाबेस निर्माण और डंप आयात सेटअप करने के बारे में कोई विचार?


यह इस तथ्य के कारण है कि प्रत्येक RUNकमांड को एक अलग कंटेनर में निष्पादित किया जाता है। यह यहाँ अच्छी तरह से समझाया गया है: stackoverflow.com/questions/17891669/…
कुहेस

यह सिर्फ यह बताता है कि RUN कमांड के अलग-अलग संदर्भ हैं। लेकिन मैं एक डेमॉन पर निर्भर करता हूं, संदर्भ नहीं।
विनीलिनक्स

1
हां, लेकिन यह बताता है कि आप MySQL से क्यों नहीं जुड़ सकते हैं। यह इसलिए है, क्योंकि यह केवल आपकी पहली RUNपंक्ति में चल रहा है ।
कुहेस

अपने SQL कथनों को निष्पादित करने के लिए, आपको MySQL शुरू करने की आवश्यकता है, और एक ही कंटेनर में MySQL क्लाइंट का उपयोग करें: एक RUNकई चरणों के साथ। आप यहां एक सॉफ़्टवेयर के बहु-चरणीय इंस्टॉलेशन के साथ एक उदाहरण पा सकते हैं: stackoverflow.com/questions/25899912/install-nvm-in-docker/…
Kuhess

आप डॉकटर - कंपोज़ के साथ सेवा पर भी एक नज़र डाल सकते हैं: docs.docker.com/compose/wordpress/#build-the-project इसके साथ, mysql को आपके ऐप पर संलग्न किया जा सकता है
aurny2420289

जवाबों:


122

प्रत्येक RUNनिर्देश को एक Dockerfileअलग परत में निष्पादित किया जाता है (जैसा कि प्रलेखनRUN में समझाया गया है )।

अपने में Dockerfile, आप तीन है RUNनिर्देश। समस्या यह है कि MySQL सर्वर केवल पहले में शुरू किया गया है। दूसरों में, कोई MySQL नहीं चल रहा है, यही कारण है कि आपको mysqlक्लाइंट के साथ आपकी कनेक्शन त्रुटि मिलती है ।

इस समस्या को हल करने के लिए आपके पास 2 समाधान हैं।

समाधान 1: एक-पंक्ति का उपयोग करें RUN

RUN /bin/bash -c "/usr/bin/mysqld_safe --skip-grant-tables &" && \
  sleep 5 && \
  mysql -u root -e "CREATE DATABASE mydb" && \
  mysql -u root mydb < /tmp/dump.sql

समाधान 2: एक स्क्रिप्ट का उपयोग करें

एक निष्पादन योग्य स्क्रिप्ट बनाएं init_db.sh:

#!/bin/bash
/usr/bin/mysqld_safe --skip-grant-tables &
sleep 5
mysql -u root -e "CREATE DATABASE mydb"
mysql -u root mydb < /tmp/dump.sql

इन पंक्तियों को अपने साथ जोड़ें Dockerfile:

ADD init_db.sh /tmp/init_db.sh
RUN /tmp/init_db.sh

क्या आपके पास कोई विचार है कि मैं उस जानकारी को कैसे जारी रख सकता हूं? जब मैं कंटेनरों पर सामान चलाता हूं तो डेटाबेस और डॉकरफाइल बिल्ड पर टेबल उपलब्ध नहीं होते हैं। :(
विनीलिनक्स

1
यह इस बात पर निर्भर करता है कि आपका क्या मतलब है। यदि आप डेटा को कई docker runनिष्पादन में बनाए रखना चाहते हैं , तो आपको वॉल्यूम को माउंट करने की आवश्यकता है। यदि आप बस अपने डंप के साथ एक कंटेनर रखना चाहते हैं, लेकिन आप आगे के संशोधनों को जारी नहीं रखना चाहते हैं, तो आप VOLUMEअपने निर्देश से छुटकारा पा सकते हैं Dockerfile
कुहेस

16
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)जब मैं समाधान 1 की कोशिश कर रहा होता हूं , तो लॉग्स का अनुसरण करता mysqld_safe Starting mysqld daemon with databases from /var/lib/mysqlmysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
हूं

1
मुझे लगता है कि mysql ने एक डेटाबेस बनाया है या नहीं यह देखने के लिए स्टार्टअप पर स्क्रिप्ट की जांच करना बहुत बेहतर है। यदि यह है, तो इसे अकेला छोड़ दें, अन्यथा mysql_init_dbअपने डेटाबेस संरचना में चलाएं और लोड करें। यह डेटाबेस के लचीलेपन की अनुमति देता है जब परीक्षण करते समय स्वचालित रूप से रीसेट किया जाता है, लेकिन यदि आप इसे अलग-अलग डेटा सेटों को जारी रखने या परीक्षण करने के लिए चाहते हैं, तो आप सिर्फ / var / lib / mysql का उपयोग करके वॉल्यूम माउंट करते हैं docker run -v ...
tu-Reinstate Monica-dor duh

1
@trevorgrayson - यह भी काम नहीं करता है। अब यह एरर 2003 (HY000) त्रुटि देता है: '127.0.0.1' (111) पर MySQL सर्वर से कनेक्ट नहीं हो सकता
दीप

166

आधिकारिक mysql docker छवि का नवीनतम संस्करण आपको स्टार्टअप पर डेटा आयात करने की अनुमति देता है। यहाँ मेरा docker-compose.yml है

data:
  build: docker/data/.
mysql:
  image: mysql
  ports:
    - "3307:3306"
  environment:
    MYSQL_ROOT_PASSWORD: 1234
  volumes:
    - ./docker/data:/docker-entrypoint-initdb.d
  volumes_from:
    - data

यहां, मेरे पास मेरा डेटा-डंप है। एसक्यूएल docker/dataजिसके तहत फोल्डर के सापेक्ष डॉकटर-कंपोज चल रहा है। मैं उस निर्देशिका में उस sql फ़ाइल को /docker-entrypoint-initdb.dकंटेनर पर माउंट कर रहा हूं ।

यदि आप यह देखना चाहते हैं कि यह कैसे काम करता है, तो docker-entrypoint.shGitHub में देखें। डेटा आयात करने की अनुमति देने के लिए उन्होंने इस ब्लॉक को जोड़ा है

    echo
    for f in /docker-entrypoint-initdb.d/*; do
        case "$f" in
            *.sh)  echo "$0: running $f"; . "$f" ;;
            *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f" && echo ;;
            *)     echo "$0: ignoring $f" ;;
        esac
        echo
    done

एक अतिरिक्त नोट, यदि आप चाहते हैं कि डेटा को mysql कंटेनर के बंद होने और हटाए जाने के बाद भी कायम रखा जाए, तो आपको एक अलग डेटा कंटेनर रखना होगा, जैसा कि आप docker-compose.yml में देखते हैं। डेटा कंटेनर Dockerfile की सामग्री बहुत सरल है।

FROM n3ziniuka5/ubuntu-oracle-jdk:14.04-JDK8

VOLUME /var/lib/mysql

CMD ["true"]

डेटा कंटेनर भी दृढ़ता के लिए शुरू राज्य में होना जरूरी नहीं है।


1
यह बेहतर उत्तर IMHO है। यह हमारे लिए एक छवि नहीं बनाने देता है। इस टिप के लिए धन्यवाद।
Metal3d

5
मात्रा के लिए एक छोटा सा - ./docker/data:/docker-entrypoint-initdb.dपरिवर्तन: -Removed .कंटेनर निर्देशिका के सामने।
डेविड सिंक्लेयर

7
हालांकि यह सही प्रक्रिया है, यह उपयोग के मामले को बहुत अच्छी तरह से संबोधित नहीं करता है। डॉकर के फायदों में से एक यह है कि आप बहुत तेज़ी से पर्यावरण बना सकते हैं। यदि आपको स्टार्ट अप के दौरान डॉकटर एक MySQL DB आयात करते समय 3-4 मिनट इंतजार करना पड़ता है, तो आप इस लाभ को खो देते हैं। उद्देश्य एक कंटेनर है जिसमें पहले से ही डेटाबेस में डेटा शामिल है, ताकि आप इसे जितनी जल्दी हो सके उपयोग कर सकें।
गैरेथ मैकडैड

3
क्या यह उत्तर अभी भी नवीनतम संस्करणों के साथ काम कर रहा है? अब काम करने के लिए प्रतीत नहीं होता है
डैनियल

2
ध्यान दें कि यहाँ docker- रचना उदाहरण v2 नहीं v3 है। "Vol_from:" v3 में समर्थित नहीं है।
अर्नेस्ट

37

मैंने जो किया था वह एक "डीबी-डंप" फ़ोल्डर में मेरे एसक्यूएल डंप को डाउनलोड किया, और इसे माउंट किया:

mysql:
 image: mysql:5.6
 environment:
   MYSQL_ROOT_PASSWORD: pass
 ports:
   - 3306:3306
 volumes:
   - ./db-dump:/docker-entrypoint-initdb.d

जब मैं docker-compose upपहली बार दौड़ता हूं , तो db में डंप को बहाल किया जाता है।


3
+1, एक जोड़ के साथ: बेहतर समझ के लिए चलाए जा रहे स्क्रिप्ट का लिंक वास्तव में क्या हो रहा है: github.com/docker-library/mariadb/blob/…
टॉम इमरेई

6
नवीनतम mysqlलगता है कि डंप किए गए एसक्यूएल फ़ाइल को लोड नहीं किया गया है, और यहां तक ​​कि 5.6 का उपयोग करते हुए मुझे इनडोड स्टोरेज इंजन के साथ समस्या है।
zinking

1
यहाँ भी, यह इस तरह के निर्देश है और मैं भी लॉग इन देखा है कि init फ़ाइलें लोड हो रहा है, लेकिन DB खाली है!
होम्स

11

मैंने docker-entrypoint-initdb.d दृष्टिकोण (@Kuhess के लिए धन्यवाद) का उपयोग किया था, लेकिन मेरे मामले में मैं अपना DB कुछ मापदंडों के आधार पर बनाना चाहता हूं जिन्हें मैंने .env फ़ाइल में परिभाषित किया था इसलिए मैंने ये किया।

1) सबसे पहले मैं परिभाषित करता हूं। मेरे docker रूट प्रोजेक्ट डायरेक्टरी में कुछ इस तरह फाइल करें

MYSQL_DATABASE=my_db_name
MYSQL_USER=user_test
MYSQL_PASSWORD=test
MYSQL_ROOT_PASSWORD=test
MYSQL_PORT=3306

2) फिर मैं अपने docker-compose.yml फ़ाइल को परिभाषित करता हूं। इसलिए मैंने अपने पर्यावरण चर को परिभाषित करने के लिए args निर्देश का उपयोग किया और मैंने उन्हें .env फ़ाइल से सेट किया

version: '2'
services:
### MySQL Container
    mysql:
        build:
            context: ./mysql
            args:
                - MYSQL_DATABASE=${MYSQL_DATABASE}
                - MYSQL_USER=${MYSQL_USER}
                - MYSQL_PASSWORD=${MYSQL_PASSWORD}
                - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
        ports:
            - "${MYSQL_PORT}:3306"

3) फिर मैं एक mysql फ़ोल्डर को परिभाषित करता हूं जिसमें एक Dockerfile शामिल है। तो डॉकरफाइल यह है

FROM mysql:5.7
RUN chown -R mysql:root /var/lib/mysql/

ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD

ENV MYSQL_DATABASE=$MYSQL_DATABASE
ENV MYSQL_USER=$MYSQL_USER
ENV MYSQL_PASSWORD=$MYSQL_PASSWORD
ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD

ADD data.sql /etc/mysql/data.sql
RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/data.sql
RUN cp /etc/mysql/data.sql /docker-entrypoint-initdb.d

EXPOSE 3306

4) अब मैं अपने db को डंप करने और mysql फ़ोल्डर के अंदर data.sql डालने के लिए mysqldump का उपयोग करता हूं

mysqldump -h <server name> -u<user> -p <db name> > data.sql

फ़ाइल एक सामान्य sql डंप फ़ाइल है, लेकिन मैं शुरुआत में 2 लाइनें जोड़ता हूं ताकि फ़ाइल इस तरह दिखे

--
-- Create a database using `MYSQL_DATABASE` placeholder
--
CREATE DATABASE IF NOT EXISTS `MYSQL_DATABASE`;
USE `MYSQL_DATABASE`;

-- Rest of queries
DROP TABLE IF EXISTS `x`;
CREATE TABLE `x` (..)
LOCK TABLES `x` WRITE;
INSERT INTO `x` VALUES ...;
...
...
...

तो क्या हो रहा है कि मैंने MYSQL_DATABASEअपने DB के नाम के साथ प्लेसहोल्डर को बदलने के लिए "RUN sed -i '/ MYSQL_DATABASE /' $ MYSQL_DATABASE '/ g' /etc/mysql/data.sql" कमांड का उपयोग किया है। .env फ़ाइल।

|- docker-compose.yml
|- .env
|- mysql
     |- Dockerfile
     |- data.sql

अब आप अपने कंटेनर को बनाने और चलाने के लिए तैयार हैं


मुझे .envफ़ाइल का उपयोग करने का दृष्टिकोण पसंद है । हालांकि के अनुसार इस , .envफ़ाइल सुविधा केवल काम करता है जब आप का उपयोग docker-compose upकमान और साथ काम नहीं करता docker stack deploy। इस प्रकार, यदि आप .envउत्पादन में फ़ाइल का उपयोग करना चाहते हैं , तो आप डॉकटर रहस्यों को देखना चाहते हैं जो इसके साथ पेश किए गए हैं docker 17.06। तब आप अपनी .env फाइल को विकास docker compose upऔर उत्पादन दोनों docker stack deployचरणों में रहस्यों के साथ संयोजन के रूप में उपयोग कर सकते हैं
ira

अच्छा तरीका है, लेकिन मैं आपको सुझाए गए आदेश के बजाय RUN sed -i '1s/^/CREATE DATABASE IF NOT EXISTS $ MYSQL_DATABASE ;\nUSE $ MYSQL_DATABASE का उपयोग करने का सुझाव दूंगा । इस तरह आप अपने पास मौजूद किसी भी डंप फ़ाइल का उपयोग कर सकते हैं - यदि आप बड़ी मात्रा में डेटा के साथ काम कर रहे हैं तो यह उपयोगी है :);\n/' data.sqlsed
टॉमसज़ कपालोस्की

9

यहाँ एक कार्यशील संस्करण का उपयोग किया गया v3है docker-compose.yml। कुंजी संस्करणों का निर्देश है:

mysql:
  image: mysql:5.6
  ports:
    - "3306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_USER: theusername
    MYSQL_PASSWORD: thepw
    MYSQL_DATABASE: mydb
  volumes:
    - ./data:/docker-entrypoint-initdb.d

निर्देशिका में है कि मेरे पास मेरा docker-compose.ymlएक dataडायर है जिसमें .sqlडंप फाइलें हैं। यह अच्छा है क्योंकि आपके पास .sqlप्रति तालिका एक डंप फ़ाइल हो सकती है ।

मैं बस दौड़ता docker-compose upहूं और मुझे जाना अच्छा लगता है। स्टॉप के बीच डेटा अपने आप बना रहता है। आप डेटा निकालना चाहते हैं और यदि नए "में चूसना" .sqlफ़ाइलों को चलाने के docker-compose downतो docker-compose up

अगर किसी को पता है कि वॉल्यूम को हटाए बिना mysqlफ़ाइलों को फिर से संसाधित करने के लिए डॉकटर कैसे प्राप्त करें /docker-entrypoint-initdb.d, तो कृपया एक टिप्पणी छोड़ दें और मैं इस उत्तर को अपडेट करूंगा।


2
इस जवाब से मुझे मदद मिली। नोट docker-compose downबहुत महत्वपूर्ण था क्योंकि मुझे डॉकटर-कंपोज़ को फिर से शुरू करने के बावजूद कोई बदलाव नहीं दिखाई दे रहा था। MYSQL_DATABASE इस मामले में एक आवश्यक चर है
nxmohamad
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.