Учебник. Создание многоконтейнерных приложений с помощью MySQL и Docker Compose

В этом учебнике содержатся сведения о многоконтейнерных приложениях. Этот учебник является продолжением предыдущих — Создание приложения Docker и предоставление к нему общего доступа с помощью Visual Studio Code. В этом расширенном руководстве вы обновите приложение для работы, как показано на этой диаграмме, и научитесь:

  • Запустите MySQL.
  • Запуск приложения с помощью MySQL.
  • Создание файла Compose.
  • Запуск стека приложений.

Diagram shows two containers labeled Todo App and MySQL connected with a line.

Использование нескольких контейнеров позволяет выделить контейнеры для специализированных задач. Каждый контейнер должен качественно выполнять одно действие.

Ниже приведены некоторые причины, по которым может быть целесообразно использовать многоконтейнерные приложения.

  • Отдельные контейнеры позволяют управлять интерфейсами API и внешними элементами иначе, чем это делают базы данных.
  • Контейнеры позволяют изолировать и обновлять версии.
  • Хотя контейнер для базы данных можно использовать локально, может потребоваться прибегнуть к управляемой службе для базы данных в рабочей среде.
  • Для выполнения нескольких процессов требуется диспетчер процессов, что усложняет запуск и завершение работы контейнера.

Предварительные требования

Этот учебник является продолжением серии, которая начинается с учебника Создание приложения Docker и предоставление к нему общего доступа с помощью Visual Studio Code. Начните с первого учебника, поскольку в нем приводятся предварительные требования. Затем выполните инструкции в следующих учебниках:

Вам также понадобятся следующее.

  • Docker Compose.

    Docker Compose входит в состав Docker Desktop для Windows или Mac. Выполните эту команду, чтобы проверить следующее:

    docker-compose version
    

    Если используется операционная система Linux, установите Docker Compose.

Как и в предыдущих учебниках, большинство задач можно выполнить в представлении ОБОЗРЕВАТЕЛЬ или представлении DOCKER в VS Code. Выберите пункты Терминал>Новый терминал, чтобы открыть окно командной строки в VS Code. Кроме того, команды можно выполнять в окне Bash. Если не указано иное, в окне Bash или в терминале VS Code можно выполнять любую команду, помеченную как Bash.

Запустите MySQL.

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

Если два контейнера находятся в одной сети, они могут взаимодействовать друг с другом. В противном случае они не могут.

Существует два способа размещения контейнера в сети: назначить его при запуске или подключить существующий контейнер. В этом примере вы создадите сеть и подключите контейнер MySQL при запуске.

  1. Создайте сеть с помощью этой команды.

    docker network create todo-app
    
  2. Запустите контейнер MySQL и подключите его к сети.

    docker run -d 
        --network todo-app --network-alias mysql 
        -v todo-mysql-data:/var/lib/mysql 
        -e MYSQL_ROOT_PASSWORD=<your-password> 
        -e MYSQL_DATABASE=todos 
        mysql:5.7
    

    Эта команда также определяет переменные среды. Дополнительные сведения см. на этой странице.

    Команда задает псевдоним сети — mysql.

  3. Получите идентификатор контейнера с помощью команды docker ps.

  4. Чтобы убедиться, что база данных работает, подключитесь к ней.

    docker exec -it <mysql-container-id> mysql -p
    

    При появлении запроса введите пароль, который вы использовали ранее.

  5. В интерпретаторе MySQL выведите список баз данных и убедитесь, что вы видите базу данных todos.

    SHOW DATABASES;
    

    Вы должны увидеть следующие выходные данные.

    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    | todos              |
    +--------------------+
    5 rows in set (0.00 sec)
    

Запуск приложения с помощью MySQL

Приложение Todo поддерживает настройку нескольких переменных среды для указания параметров подключения MySQL.

  • MYSQL_HOST — имя узла для сервера MySQL.
  • MYSQL_USER — имя пользователя, используемое для подключения.
  • MYSQL_PASSWORD — пароль, используемый для подключения.
  • MYSQL_DB — база данных, которая будет использоваться после подключения.

Предупреждение

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

Более безопасный механизм заключается в использовании поддержки секрета, предоставляемой платформой оркестрации контейнеров. В большинстве случаев эти секреты подключаются как файлы в работающем контейнере.

Эта процедура запускает приложение и подключает этот контейнер к вашему контейнеру MySQL.

  1. Используйте следующую команду docker run. Она указывает переменные среды, приведенные выше.

    docker run -dp 3000:3000 
      -w /app -v ${PWD}:/app 
      --network todo-app 
      -e MYSQL_HOST=mysql 
      -e MYSQL_USER=root 
      -e MYSQL_PASSWORD=<your-password> 
      -e MYSQL_DB=todos 
      node:12-alpine 
      sh -c "yarn install && yarn run dev"
    
  2. В VS Code в представлении Docker щелкните контейнер приложения правой кнопкой мыши и выберите Просмотреть журналы. Чтобы просмотреть журналы из командной строки, используйте команду docker logs.

    Результат содержит строку, указывающую, что приложение подключено к базе данных MySQL.

    # Previous log messages omitted
    $ nodemon src/index.js
    [nodemon] 1.19.2
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching dir(s): *.*
    [nodemon] starting `node src/index.js`
    Connected to mysql db at host mysql
    Listening on port 3000
    
  3. В браузере введите http://localhost:3000. Добавьте несколько элементов в список дел.

  4. Подключитесь к базе данных MySQL, как вы это сделали в предыдущем разделе. Выполните эту команду, чтобы убедиться, что элементы записываются в базу данных.

    docker exec -ti <mysql-container-id> mysql -p todos
    

    В оболочке MySQL выполните следующую команду.

    select * from todo_items;
    

    Результат будет выглядеть так, как показано ниже.

    +--------------------------------------+--------------------+-----------+
    | id                                   | name               | completed |
    +--------------------------------------+--------------------+-----------+
    | c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! |         0 |
    | 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome!        |         0 |
    +--------------------------------------+--------------------+-----------+
    

На данный момент у вас есть приложение, которое хранит данные во внешней базе данных. Эта база данных работает в отдельном контейнере. Вы узнали о сетевых подключениях контейнеров.

Создание файла Docker Compose

Docker Compose помогает определять многоконтейнерные приложения и предоставлять к ним общий доступ. Используя Docker Compose, можно создать файл для определения служб. С помощью одной команды можно выполнить запуск или завершить работу.

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

  1. В корне проекта приложения создайте файл с именем docker-compose.yml.

  2. Написание файла Compose начнем с определения версии схемы.

    version: "3.7"
    

    В большинстве случаев лучше использовать последнюю поддерживаемую версию. Сведения о текущей версии схемы и матрицу совместимости см. на странице Файл Compose.

  3. Определите службы или контейнеры, которые будут использоваться как часть приложения.

    version: "3.7"
    
    services:
    

    Совет

    В YML-файлах важен отступ. При редактировании в VS Code технология IntelliSense указывает на ошибки.

  4. Вот команда, которую вы использовали в контейнере приложения. Вы добавите эти сведения в YML-файл.

    docker run -dp 3000:3000 
      -w /app -v ${PWD}:/app 
      --network todo-app 
      -e MYSQL_HOST=mysql 
      -e MYSQL_USER=root 
      -e MYSQL_PASSWORD=<your-password> 
      -e MYSQL_DB=todos 
      node:12-alpine 
      sh -c "yarn install && yarn run dev"
    

    Определите запись службы и образ для контейнера.

    version: "3.7"
    
    services:
      app:
        image: node:12-alpine
    

    Для службы можно выбрать любое имя. Имя автоматически преобразуется в сетевой псевдоним, что полезно при определении службы MySQL.

  5. Добавьте команду.

    version: "3.7"
    
    services:
      app:
        image: node:12-alpine
        command: sh -c "yarn install && yarn run dev"
    
  6. Укажите порты для службы, которые соответствуют -p 3000:3000 в приведенной выше команде.

    version: "3.7"
    
    services:
      app:
        image: node:12-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
    
  7. Укажите рабочий каталог и сопоставление томов.

    version: "3.7"
    
    services:
      app:
        image: node:12-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
        working_dir: /app
        volumes:
          - ./:/app
    

    В определениях томов Docker Compose можно использовать относительные пути из текущего каталога.

  8. Укажите определения переменных среды.

    version: "3.7"
    
    services:
      app:
        image: node:12-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
        working_dir: /app
        volumes:
          - ./:/app
        environment:
          MYSQL_HOST: mysql
          MYSQL_USER: root
          MYSQL_PASSWORD: <your-password>
          MYSQL_DB: todos
    
  9. Добавьте определения для службы MySQL. Ниже приведена команда, которая использовалась ранее.

    docker run -d 
      --network todo-app --network-alias mysql 
      -v todo-mysql-data:/var/lib/mysql 
      -e MYSQL_ROOT_PASSWORD=<your-password> 
      -e MYSQL_DATABASE=todos 
      mysql:5.7
    

    Определите новую службу и назовите ее mysql. Добавьте текст после определения app на том же уровне отступа.

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
    

    Служба автоматически получает псевдоним сети. Укажите образ, который будет использоваться.

  10. Определите сопоставление томов.

    Укажите том с разделом volumes: на том же уровне, что и services:. Укажите сопоставление тома под образом.

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
        volumes:
          - todo-mysql-data:/var/lib/mysql
    
    volumes:
      todo-mysql-data:
    
  11. Укажите переменные среды.

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
        volumes:
          - todo-mysql-data:/var/lib/mysql
        environment: 
          MYSQL_ROOT_PASSWORD: <your-password>
          MYSQL_DATABASE: todos
    
    volumes:
      todo-mysql-data:
    

На данный момент этапе полный файл docker-compose.yml выглядит следующим образом:

version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: <your-password>
      MYSQL_DB: todos

  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: <your-password>
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

Запуск стека приложений

Теперь, когда у вас есть файл docker-compose.yml, попробуйте поработать с ним.

  1. Убедитесь, что никакие другие копии приложения и базы данных не запущены. В расширении Docker щелкните правой кнопкой мыши любой выполняющийся контейнер и выберите команду Удалить. Или в командной строке используйте команду docker rm, как в предыдущих примерах.

  2. В Обозревателе VS Code щелкните правой кнопкой мыши файл docker-compose.yml и выберите Создать. Или в командной строке используйте эту команду Docker.

    docker-compose up -d
    

    Параметр -d позволяет выполнять команду в фоновом режиме.

    Вы должны увидеть выходные данные, аналогичные приведенным ниже.

    Creating network "app_default" with the default driver
    Creating volume "app_todo-mysql-data" with default driver
    Creating app_app_1   ... done
    Creating app_mysql_1 ... done
    

    Были созданы том и сеть. По умолчанию Docker Compose создает сеть специально для стека приложений.

  3. В расширении Docker щелкните контейнер приложения правой кнопкой мыши и выберите Просмотреть журналы. Чтобы просмотреть журналы из командной строки, используйте команду docker logs.

    mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
    mysql_1  | Version: '5.7.27'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    app_1    | Connected to mysql db at host mysql
    app_1    | Listening on port 3000
    

    Отображаются журналы каждой из служб, которые чередуются в одном потоке. Это поведение позволяет отслеживать проблемы, связанные с временем.

    Имя службы отображается в начале строки, чтобы упростить различение сообщений. Чтобы просмотреть журналы для определенной службы, добавьте имя службы в конец команды logs.

  4. На этом этапе вы сможете открыть приложение. В браузере введите http://localhost:3000.

Когда вы завершите работу с этими контейнерами, их легко можно будет удалить.

  • В Обозревателе VS Code щелкните правой кнопкой мыши файл docker-compose.yml и выберите Удалить.
  • В командной строке выполните команду docker-compose down.

Контейнеры останавливаются. Сеть удаляется.

По умолчанию именованные тома в файле Compose не удаляются. Чтобы удалить тома, выполните команду docker-compose down --volumes.

Очистка ресурсов

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

Дальнейшие действия

Из этого учебника вы узнали о многоконтейнерных приложениях и Docker Compose. Docker Compose существенно упрощает определение и совместное использование приложений с несколькими службами.

Ниже приведены некоторые ресурсы, которые могут быть полезны: