LINUX.ORG.RU
решено ФорумAdmin

миграция на docker-compose (mysql+api)

 


0

1

Приветствую, вопрос следующий, пытаюсь связать 2 отдельных docker контейнера в docker-compose, но постоянно натыкаюсь на грабли то в одном то в другом.

Вкратце, сейчас логика развертывания в текущих отдельных контейнерах следующая:

1.1 docker run mysql:latest, dockerfile этого контейнера (в упрощнном виде):

--- FROM mysql:latest
--- RUN apt-get install wget
--- RUN wget <db_dump.sql>

1.2 docker exec mysql "mysql < <db_dump.sql>"

  1. docker run sinatra (connect mysql:3306)

Мигрирую на docker-compose и сразу же натыкаюсь на ворох проблем:

1) Как правильно организовать логику скачивания дампа базы wget’ом и закачивания её в mysql?

Мейнтейнеры образа предлагают шарить volume с дампами, которые будут залиты, мне этот подход не рабоатет тк мне надо слить образы wget’ом, который, кстати, на борту образа не присутсвует.

Пробовал в compose создавать build context со ссылкой на dockerfile по подобию оригинального докерфайла:

docker-compose.yml:
version: '3'
services:
  db:
    build: ./db
db/Dockerfile: (упрощённо):
-- FROM mysql:latest
-- RUN apt-get install wget
-- RUN wget <db_dump.sql>
-- RUN mysql < <db_dump.sql>

Этот подход не рабочий, так как логика запуска mysqld для этого image обёрнута wrapper’ом, который запускается ENTRYPOINT’ом по умолчанию. То есть строка «RUN mysql..» не отработает тк mysqld в этот момент будет не запущен.

Есть вариант обновить Entrypoint по умолчанию, добавив туда нужную логику сверху, но это КМК совсем грязный хак учитывая типовость задачи.

Гугление навело на stackoverflow где оптимальным решением было принято создание -1) просто mysql контейнера без дампа и -2) доп контейнера где отрабатывает wget и , собственно, mysql < <dump> .

Может есть менее кривые способы?

2) Если всё таки завести 2-й контейнер,

упрощаю освной mysql до

version: '3'
services:
  db:
    image: mysql:latest
    ports:
      - "3306:3306"
    tty: true
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
  • доавляю новый контейнер в docker-compose (фрагмент):
  mysql-seed:
    build: ./db-seed
    ports:
      - "3307:3306"
    tty: true
    depends_on:
      - db
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}

где, в свою очередь ./db-seed/Dockerfile выглядит примерно так:

FROM mysql:latest

ARG MYSQL_ROOT_PASSWORD
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_DATABASE

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    wget unzip less vim \
     mysql-client iputils-ping

RUN ping -c2 db

и вот тут интересное, когда этот контейнер собирается, он не видит хоста «db», то есть будь-то пинги, будь то логика залива дампа - на этом этапе не может отработать, так как хост 1-ого контейнера не виден.

Если же я закомментриую RUN ping db, стартанну стек через docker-compose up , дождусь пока контейнеры поднимуться , залогинюсь на mysql-seed и вручную пингану db/запущу залив дампа - всё ок, всё отрабатывает. Хост виден.

Что я делаю не так? На этапе build контейнер не должен видеть другие контейнеры?

Если так, то как тогда наиболее канонично запилить такую логику?

Пост не читал, но ты делаешь не так абсолютно всё. docker-compose не для прода, а для разработки и тестирования, а за MySQL в контейнере — вон из професии. Ты кто по должности и почему старшие позволяют тебе такое воротить?

WitcherGeralt ★★ ()
Ответ на: комментарий от WitcherGeralt

причём тут прод вообще? Всё что я делаю - собираю стек для возможности быстрого развёртывания в любом окружении.

а за MySQL в контейнере — вон из професии.

это почему? Аргументы?

epsilon1024 ()
Ответ на: комментарий от epsilon1024

Ты даже данные никуда не примонтировал для персистентности, какие тебе ещё аргументы? Ты попросту не одупляешь, что делаешь.

Какой в жопу пинг на этапе сборки, какой нахрен залив дампа, алё? Собирать ты можешь на одном хосте сегодня, а запускать на другом через неделю. И разберись с тем как файловая система в контейнере работает, а то стыд испанский.

WitcherGeralt ★★ ()
Последнее исправление: WitcherGeralt (всего исправлений: 1)


По теме, второй контейнер можно без mysql а просто какой либо стандартный Alpine и там уже поставить mysql-tools внутри.

и вот тут интересное, когда этот контейнер собирается, он не видит хоста «db», то есть будь-то пинги, будь то логика залива дампа - на этом этапе не может отработать, так как хост 1-ого контейнера не виден.

На момент собирания пакета Dockerfile-ом, он еще не добавляется в network, вся логика должна быть потом, популярное решение это скрипт который ждет пока успешно отработает ping, либо Wait-for-it

shuck ★★★ ()
Ответ на: комментарий от shuck

Раздел Admin, в заголовке «миграция на docker», про локальное окружение ни слова.

При этом чувак даже не заглядывал в документацию, не понимает разницы между образом и контейнером. Меж тем, тут в последнее время тут и вовсе банили за «троллинг тупостью», так что не понимаю твоего бурления.

WitcherGeralt ★★ ()

Мне кажется зашивать дамп базы внутрь image концептуально неверно. Соответственно надо подпихнуть его именно при запуске контейнера.

Вариант 1. Поменять логику старта mysql в контейнере, добавив скрипт, который загрузит базу.

Вариант 2. Сделать загрузку базы внешним инструментом, например вторым контейнером.

Вариант 3. Примонтировать volume, где перед запуском контейнера будет размещен дамп базы.

samson_b ()

На этапе build контейнер не должен видеть другие контейнеры?

Нет. На этапе сборки в доступе нет ничего, кроме билд-директории, интернета и переданных переменных окружения.

Если так, то как тогда наиболее канонично запилить такую логику?

Все стандартные сервисные контейнеры, вроде мускуля, используешь как есть, в соответствии с их документацией. Для своего приложения создаёшь свой контейнер, и всё наполнение сервисных контейнеров контентом запихиваешь в скрипт запуска внутри своего контейнера. Если тебе надо сохранять данные между запусками - читай ещё раз про volumes и пиши свой скрипт соответствующе, что бы он не перетирал данные если они уже есть.

Что я делаю не так?

По большей части всё на данный момент. Мне кажется тут дело не в том, что именно ты делаешь, а в непонимании концепции докера и микросервисов в целом. Попробуй начать знакомство ещё раз, тут основные идеи могут показаться местами контринтуитивными.

manntes-live ★★ ()
Последнее исправление: manntes-live (всего исправлений: 1)