Как я могу сохранить свою базу данных, но изменить код в docker-compose?

У меня есть веб-сервис Python + MySQL, работающий на дроплете Digital Ocean в производстве. Когда я обновляю код в проекте на своем локальном компьютере, я хочу, чтобы изменения происходили и в дроплете (в производстве). Поэтому я делаю следующее для развертывания:

$ ssh [email protected]
# cd project
# git pull
# docker-compose down
# docker-compose build
# docker-compose up -d

После этого моя база данных пуста. В нем нет ни одной из моих таблиц. Как я могу обновить код, который работает, но не потерять данные?

Мой код

Структура проекта

.
├── db
├── docker-compose.yml
└── web
    ├── Dockerfile
    ├── project
    │   ├── app.py
    │   ├── __init__.py
    │   ├── blueprint1
    │   ├── blueprint2
    │   ├── models.py
    │   ├── static
    │   ├── templates
    │   └── _version.py
    ├── Makefile
    ├── migrations
    ├── README.md
    ├── setup.cfg
    ├── setup.py
    ├── start.sh
    ├── tests
    └── tox.ini

докер-compose.yml

version: "2"
services:
  db:
    image: mysql:5.7
    ports:
      - "32000:3306"
    environment:
      MYSQL_DATABASE: ***
      MYSQL_ROOT_PASSWORD: ***
    volumes:
      - ./db:/docker-entrypoint-initdb.d/:ro
  app:
    build: ./web
    links:
      - db
    ports:
      - "5000:5000"
    environment:
      MYSQL_PORT: 32000

Докерфайл

FROM python:3.7-slim

# Copy projects code
RUN apt-get update && apt-get install -y git
COPY . /opt/app
WORKDIR /opt/app
RUN pip install -e . --no-cache-dir

# Start app
ENV ENV=prod
EXPOSE 5000
ENTRYPOINT ["sh", "start.sh"]
CMD ["/opt/app/start.sh"]

Что я пробовал

# This killed my data:
$ docker-compose up -d --build app

# This did NOT update the code in app:
# 1
$ docker-compose stop app && docker-compose up -d app
# 2
$ docker-compose up -d --no-deps --build app

Может быть напрямую связано с stackoverflow.com/q/56486763/562769

Martin Thoma 07.06.2019 02:59

Что это на самом деле делает с вашей базой данных, вы используете расплывчатые слова, такие как kill и nuke? Если вы правильно определили том, он не должен потерять данные при резервном копировании.

Shardj 07.06.2019 18:31

Я понятия не имею, что он делает с ним. Я просто могу сказать, что таблиц больше не существует (база данных существует, но она совершенно пуста)

Martin Thoma 07.06.2019 18:45

Я думаю, что он полностью повторно инициализирует его. Таким образом, он перезаписывает том новым. Но это чистое предположение.

Martin Thoma 07.06.2019 18:46

«Вы правильно определили том, тогда он не должен потерять данные при резервном копировании» - как мне правильно определить том? Я опубликовал все, что сделал.

Martin Thoma 07.06.2019 21:04

Ну, в вашем объявлении тома есть два двоеточия, что, насколько я знаю, не является правильным синтаксисом, но я могу ошибаться.

Shardj 08.06.2019 02:37

Можете ли вы опубликовать свой файл start.sh, возможно, он делает перезапись. Если у вас все еще есть база данных, но нет таблиц, то я не думаю, что это проблема объема. Какой-то ваш код, вероятно, стирает его.

Shardj 10.06.2019 12:23

Хахахах, нашел. Я вообще не использовал базу данных MySQL ?. Я использовал локальную базу данных контейнера sqlite. Конечно, этого тогда уже не было. Я пробегусь по комментариям/вопросу, чтобы потом не запутаться.

Martin Thoma 10.06.2019 12:27
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
4
8
9 382
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

  1. Создать папку на хост-машине
mkdir /data/mysql
  1. Запустите MySQL в докере
  2. Скопируйте базу данных из работающего контейнера MySQL на хост-компьютер
docker ps | grep mysql
docker cp <container_id>:/var/lib/mysql /data/mysql
  1. Внесите изменения в свой docker-compose.yml
    volumes:
      - ./db:/docker-entrypoint-initdb.d/:ro
      - /data/mysql:/var/lib/mysql
  1. Перезапустите все.

Это не решает мою проблему. Когда я делаю эти изменения, а затем перехожу к рабочему процессу «вниз, сборка, вверх», я все равно теряю свои данные.

Martin Thoma 04.06.2019 23:10

Для подтверждения: БД MySQL по-прежнему является частью docker-compose, верно? Итак, «запустить mysql в докере» означает docker-compose up db? Что означает «перезапустить все» как команду?

Martin Thoma 07.06.2019 18:24

Если вы просто хотите обновить контейнер app, не касаясь контейнера db, почему бы и нет?

docker-compose down app
docker-compose up app

В этом случае вы просто перестраиваете свой app контейнер, не касаясь db контейнера.

А также рекомендуется сохранять ваши контейнеры без гражданства. Храните данные mysql на локальном компьютере, как предлагает Qteb.

Спасибо.

Будет ли это фактически перестраивать контейнер приложения? Или он просто выключит его/запустит снова тот же контейнер?

Martin Thoma 06.06.2019 18:51

Он отключает все, например, контейнер, образ, том и сеть, и снова перезагружается. Это рекомендуемый способ. Перейдите по этой ссылке для получения информации stackoverflow.com/questions/41322541/…

Himakar 06.06.2019 18:55

Так что, думаю, на практике я буду называть это как docker-compose down app && docker-compose up -d app

Martin Thoma 06.06.2019 19:13

Это сохраняет данные, но не обновляет контейнер. Я только что попробовал.

Martin Thoma 06.06.2019 19:15

он не обновляет контейнер? Мы все еще говорим о контейнере приложений?

Himakar 06.06.2019 19:18

Ну не помогло. Как я уже писал, он НЕ обновлял код. Также docker-compose stop app && docker-compose up -d app не обновил код.

Martin Thoma 06.06.2019 19:19

Да, я говорю о контейнере приложения.

Martin Thoma 06.06.2019 19:19
docker-compose down app && docker-compose up -d app следует перезапустить контейнер. docker-compose stop app не изменит код
Himakar 06.06.2019 19:19

Вы, ребята, забыли сборку docker-compose?

Shardj 07.06.2019 17:28
docker-compose up создает изображение, если оно еще не существует.
Himakar 08.06.2019 06:07

Выяснил, что проблема была в другом. Не могли бы вы добавить некоторую информацию о томах (например, в чем разница между «томами:» в службе и «томами:» на том же уровне, что и «службы:»? Когда тома создаются/уничтожаются?). Если вы добавите это, я дам вам награду и приму ваш ответ.

Martin Thoma 10.06.2019 12:31

Это просто. Внешние тома похожи на глобальные. Их можно повторно использовать с другими службами, а также по имени. Если вам не нужен многоразовый том, не называйте его. Просто дайте путь. И с точки зрения docker-compose, когда контейнер инициируется, создаются тома, если они еще не выходят. Они не уничтожаются по команде stop. Они уничтожаются по команде down.

Himakar 10.06.2019 15:56
Ответ принят как подходящий

Вы должны создать именованный том для своей базы данных, например

version: '3'

services:    
  mysql:
    image: mysql:5.7
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

Теперь вы можете безопасно запускать docker-compose stop или docker-compose down без потери данных на томе mysql_data. Только когда вы запустите docker-compose down -v, он также удалит громкость.

Вы можете увидеть все ваши именованные тома, запустив docker volume ls

Краткое примечание: docker-compose предназначен для разработки, а не для производства. Возможно, вы захотите рассмотреть другую стратегию.

«Возможно, вы захотите рассмотреть другую стратегию». Не могли бы вы добавить сюда несколько примеров?

Martin Thoma 13.06.2019 07:16

Судя по этой странице docs.docker.com/compose/production, можно запускать ее с docker-compose. Другие решения, такие как docker swarm и kubernetes, более сложны и, вероятно, немного излишни в вашем случае.

Chris 13.06.2019 10:31

Во-первых, вам нужно иметь именованный том для сохранения данных, как упоминал Крис.

Затем создайте образ кода и запустите контейнер из нового образа по отдельности:

docker-compose up -d --no-deps --build app

Флаг --no-deps не запускает никакие связанные службы. Связанные службы запускаются по умолчанию. Это уничтожит ваши данные (например, когда вы это сделали docker-compose up -d --build app).

Использованная литература:

Чтобы сохранить базу данных mysql или другие данные базы данных, убедитесь, что ваш docker-compose.yml будет выглядеть так: 1.если вы хотите использовать Dockerfile

version: '3.1'

services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 80:80
    volumes:
      - ./src:/var/www/html/
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example
    volumes:
      - mysql-data:/var/lib/mysql

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
volumes:
  mysql-data:

2. если вы хотите использовать свой образ вместо Dockerfile, ваш docker-compose.yml будет выглядеть так:

version: '3.1'   

services:
  php:
    image: php:7.4-apache
    ports:
      - 80:80
    volumes:
      - ./src:/var/www/html/
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example
    volumes:
      - mysql-data:/var/lib/mysql

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
volumes:

если вы хотите хранить или сохранять данные mysql, тогда не забудьте добавить две строки в ваш docker-compose.yml

volumes:
  - mysql-data:/var/lib/mysql

а также

volumes:
  mysql-data:

после этого используйте эту команду

docker-compose up -d

теперь ваши данные будут постоянными и не будут удалены даже после использования этой команды

docker-compose down

дополнительно: - но если вы хотите удалить все данные, вы будете использовать

docker-compose down -v

плюс вы можете проверить список данных вашей базы данных с помощью этой команды

docker volume ls

DRIVER              VOLUME NAME
local               35c819179d883cf8a4355ae2ce391844fcaa534cb71dc9a3fd5c6a4ed862b0d4
local               133db2cc48919575fc35457d104cb126b1e7eb3792b8e69249c1cfd20826aac4
local               483d7b8fe09d9e96b483295c6e7e4a9d58443b2321e0862818159ba8cf0e1d39
local               725aa19ad0e864688788576c5f46e1f62dfc8cdf154f243d68fa186da04bc5ec
local               de265ce8fc271fc0ae49850650f9d3bf0492b6f58162698c26fce35694e6231c
local               phphelloworld_mysql-data

Другие вопросы по теме