Рубрики
Uncategorized

Узнайте докер — с самого начала, часть V Docker составляют, переменные, объемы, сети и базы данных

Следуйте за мной в Twitter, рады брать ваши предложения по темам или улучшениям / Крису этой статьи … Теги с докером, начинающими, дежопами, учебником.

Докер (5 части серии)

Следуй за мной на Twitter , рад принять ваши предложения по темам или улучшениям/Крису

Эта статья является частью серии:

  • Докер — с самого начала, часть Я Этот охватывает: почему докер, как он работает и охватывает некоторые основные концепции, такие как изображения, контейнеры и использование DockerFile. Он также вводит некоторые основные команды Docker о том, как управлять вышеуказанными концепциями.
  • Докер — с самого начала, часть II Речь идет о том, что узнать о объемах, то, что они есть, как они могут работать для вас и в первую очередь, как они создадут удивительную среду развития
  • Докер — с самого начала, часть III Эта часть состоит в том, чтобы понять, как работать с базами данных в контейнерной среде и при этом мы должны узнать о связывании и сетях
  • Докер — с самого начала , Часть IV, эта часть представляет Docker Compose, и мы узнаем, как управлять большим количеством контейнеров, и мы узнаем, почему Docker Compose лучше использовать, чем просто команда Docker
  • Докер — с самого начала, часть v, мы здесь

Мы будем продолжать работать над нашим проектом, представленным в части IV и при этом мы будем продемонстрировать больше функций Pocker Compose и по сути, построив наш проект, чтобы покрыть все возможное.

В этой части мы будем охватывать:

  • Переменные среды , теперь мы охватывали эти предыдущие части, так что это в основном о том, как мы устанавливаем их в Docker Compose
  • Объемы , то же самое с объемами, это было охвачено предыдущим статьям, хотя мы упомянем их использование и как работать с ними с Docker Compose
  • Сети и базы данных , наконец, мы будем охватывать базы данных и сети, эта часть немного сложная, но надеюсь, нам удалось полностью объяснить

Если вы в любой момент должны смущаться здесь, это репо, эта статья основана на:

https://github.com/softchris/docker-compose-experiments

Ресурсы

Использование Docker и Containeruration — это о разрыве монолита в микросервисам. На протяжении этой серии мы научимся освоить Docker и все его команды. Рано или поздно вы захотите забрать свои контейнеры в производственную среду. Эта среда обычно облака. Когда вы чувствуете, что у вас есть достаточно опыта Docker, посмотрите на эти ссылки, чтобы увидеть, как Docker можно использовать в облаке:

  • Контейнеры в облаке Отличная страница обзора, которая показывает, что еще есть, нужно знать о контейнерах в облаке
  • Развертывание ваших контейнеров в облаке Учебное пособие, которое показывает, насколько легко использовать существующие навыки Docker и получите свои услуги в облаке
  • Создание реестра контейнера Ваши изображения Docker могут быть в Docker Hub, но и в реестре контейнера в облаке. Разве не было бы здорово сохранить ваши изображения где-то и на самом деле иметь возможность создавать услугу от этого реестра в считанные минуты?

Переменные среды

Одна из вещей, которые я показал вам в предыдущих статьях, так это то, как мы можем указать переменные среды. Теперь переменные могут быть установлены в Dockerfile Но мы можем определенно установить их в командной строке и тем самым также в Docker Compose и специально в Docker-Compose.yml :

// docker-compose.yaml

version: '3'
services:
 product-service:
   build:
     context: ./product-service
   ports:
     - "8000:3000"
   environment:  
     - test=testvalue 
 inventory-service:
   build:
     context: ./inventory-service
   ports:
   - "8001:3000"

Выше мы создаем переменную среды, определяя среду, а затем -test = testValue , что означает, что мы создаем переменное тест со значением, TestValue Отказ

Мы можем легко проверить, что это работает, чтение от Process.env.test в нашем файле App.js для каталога службы продукта.

Другой способ проверить это — запускать Docker Compose и запрос для того, что доступны переменные среды, например:

Как вы можете видеть выше, мы сначала запускаем Docker-Compose PS и получите часть контейнеров, которые являются частью этого составной сессии Docker, а затем мы запускаем Docker Exec [Имя контейнера] env Чтобы перечислить переменные среды. Третий вариант — запускать Docker Exec -it [Имя контейнера] Bash и введите контейнер и используйте Bash, чтобы повторить значение переменной. Существует довольно много способов управления переменными среды с помощью Docker Compose, поэтому прочитайте в Официальные документы Что еще вы можете сделать.

Тома

Мы покрывали объемы в более ранней части этой серии, и мы нашли их отличным способом:

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

Создать постоянное пространство

Давайте посмотрим, как мы можем иметь дело с объемами в Docker Compose:

// docker-compose.yml

version: '3.3'
services:
 product-service:
   build:
     context: ./product-service
   ports:
     - "8000:3000"
   environment:
     - test=testvalue
 inventory-service:
   build:
     context: ./inventory-service
   ports:
     - "8001:3000"
  volumes:  
    - my-volume:/var/lib/data

volumes:  
  my-volume:

Выше мы создаем объем объема команд в конце файла и во втором ряду мы даем ему имя Мой-тома Отказ Кроме того, в части инвентаризации-сервиса нашего файла мы ссылаемся на просто созданный объем и создаем сопоставление на /var/lib/data который является каталогом в объеме, который будет сохраняться, благодаря разрывам. Давайте посмотрим, что это правильно сопоставлено:

Как видно, по вышеуказанной команде мы впервые вводим в контейнер с Docker Exec За последующим нами на нашем каталоге картирования, он там, отлично:).

Давайте создадим файл в каталоге данных, чтобы мы могли доказать, что наше сопоставление громкости действительно работает:

echo сохраняется> supist.log

Вышеуказанная команда создает файл Persist.log с контентом сохраняется. Ничего фантастического Но он создает файл, который мы можем искать после разрыва и перезапущении нашего контейнера.

Теперь мы можем выйти из контейнера. Далее давайте повторимся на некоторых полезных командах объема:

Docker Volume Ls.

Вышеуказанные перечислены все текущие монтируемые тома. Мы можем видеть, что наш созданный том — это составные эксперименты_Ми-тома.

Мы можем погрузиться в более подробную информацию с:

Docker Volume осматривает составные эксперименты_my-тома

Хорошо, так что это дает нам некоторые детали о нашем объеме, например Контрольная точка , где файлы будут сохраняться, когда мы пишем в наш каталог сопоставления объема в контейнере.

Давайте теперь сбиваем наши контейнеры:

докер-состав

Это означает, что объем все равно должен быть там, так что давайте принесем их всеми с:

Docker-Compose up -d

Давайте введем контейнер следующим образом и посмотрите, есть ли наш файл supist.log:

О да, это работает.

Поверните свой текущий каталог в объем

Хорошо, для этого нам нужно добавить новый том, и нам нужно указать каталог на нашем компьютере и место в контейнере, который должен быть в синхронизации. Ваш Docker-Compose.yaml Файл должен выглядеть как следующее:

// docker-compose.yaml

version: '3.3'
services:
  product-service:
    build:
      context: ./product-service
    ports:
      - "8000:3000"
    environment:
      - test=testvalue
    volumes:  
      - type: bind  
      source: ./product-service  
      target: /app  
  inventory-service:
    build:
      context: ./inventory-service
    ports:
      - "8001:3000"
    volumes:
      - my-volume:/var/lib/data

volumes:
  my-volume:

Новое дополнение добавляется в Продукт-сервис Отказ Мы видим, что указываем команду тома с одной записью. Давайте сломаем эту запись:

  • Тип: Bind это создает так называемый привязать гору , тип объема больше подходит для целей синхронизации файлов между вашим локальным каталогом и вашим контейнером
  • Источник , это просто где ваши файлы, как вы можете видеть, мы указываем ./product-service Отказ Это означает, что, как только мы изменим файл под этим каталогом Docker, заберут на нем.
  • цель , это каталог в контейнере, источника и цели теперь будет синхронно, мы делаем изменение источника, одинаковые изменения произойдут с целью

Сети и базы данных

Хорошо, это последняя часть, которую мы стремимся покрыть эту статью. Давайте начнем с баз данных. Все основные поставщики имеют образец Docker, как SQL Server, Postgres, MySQL и так далее. Это означает, что нам не нужно делать шаг сборки, чтобы получить их и запустить Но нам нужно настроить такие вещи, как переменные среды и, конечно, открывают порты, чтобы мы могли взаимодействовать с ними. Давайте посмотрим, как мы можем добавить базу данных MySQL в наше решение, это наше Docker-Compose.yml файл.

Добавление базы данных

Добавление базы данных на Docker-Compose.yml.yml.yml о добавлении уже предварительного изображения. Счастливчик за нас MySQL уже дает готовый. Чтобы добавить его, нам просто нужно добавить еще одну запись под услугами: вроде так:

// docker-compose.yaml

product-db:
  image: mysql
  environment:
    - MYSQL_ROOT_PASSWORD=complexpassword
  ports:
    - 8002:3306

Давайте сломаемся:

  • Продукт-дБ Это название нашей новой записи службы, мы выбираем это имя
  • изображение Это новая команда, которую мы используем вместо сборки, мы используем это, когда изображение уже построено, которое верно для большинства баз данных
  • окружающая среда Большинство баз данных необходимо иметь определенное количество переменных, установленных, чтобы иметь возможность подключаться к ним, как имя пользователя, пароль и потенциально имя базы данных, это зависит от типа базы данных. В этом случае мы устанавливаем MySQL_ROOT_PASSSWORD, поэтому мы указываем экземпляр MySQL, что является паролем для пользователя root. Мы должны рассмотреть возможность создания ряда пользователей с различными уровнями доступа
  • Порты, это разоблачает порты, которые будут открыты и тем самым это наш вход для разговора с базой данных. Набрав 8002: 3306 Мы говорим, что порт контейнера 3306 следует сопоставить на внешний порт 8002.

Давайте посмотрим, сможем ли мы получить базу данных и остальные наши услуги и запустить:

Docker-Compose up -d

Давайте проверим с:

Docker-Compose PS или Docker PS

Выглядит, хорошо, наша служба базы данных Experiments_Product-db_1 кажется, работает и работает на порту 8002 Отказ Давайте посмотрим, сможем ли мы подключиться к базе данных дальше. Приведенная ниже команда подключится к базе данных, скрещенные пальцами;)

mysql -uroot -pcomplexpassword -h 0.0.0.0 -P 8002

и победителем становится…

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

Подключение к базе данных

Есть три основных способа, которыми мы могли бы подключиться к базе данных:

  • Используя Docker Client, мы попробовали это уже с mysql -uroot -pcomplexpassword -h 0.0.0.0-p 8002
  • Введите наш контейнер, мы делаем это, используя Docker Exec -it. [Название контейнера] Bash а потом мы вводим MySQL внутри контейнера
  • Подключение через наше приложение, это то, что мы будем смотреть на дальше, используя библиотеку NPM MySQL

Мы сосредоточимся на третьем выборе, подключев к базе данных через наше приложение. База данных и приложение будут существовать в разных контейнерах. Так как же мы заставляем их подключиться? Ответ:

  • должен быть в той же сети для двух контейнеров, чтобы поговорить друг с другом, они должны быть в одной сети
  • База данных должна быть готова , требуется некоторое время, чтобы запустить базу данных, и для вашего приложения сможет поговорить с базой данных, необходимой вам, чтобы гарантировать, что база данных запустится правильно, это была веселье/интересный/болезненный пока я не разобрался, так что не волнуйтесь, я получил тебя, нам удастся:)
  • Создайте объект подключения Убедитесь, что мы правильно настроили объект подключения в app.js для Продукт-сервис

Давайте начнем с первого предмета здесь. Как мы получаем базу данных и контейнер в ту же сеть? Легко, мы создаем сеть, и мы размещаем каждый контейнер в этой сети. Давайте покажем это в Docker-Compose.yml :

// excerpt from docker-compose.yaml

networks:
  products:

Нам нужно назначить эту сеть каждой услуге, например:

// excerpt from docker-compose.yaml

services:
  some-service:
    networks:  
      - products

Теперь для второй точки пули, как мы знаем, что база данных завершена инициализация? Ну, у нас есть недвижимость под названием Defends_on С помощью этого свойства мы можем указать, что один контейнер должен дождаться другого контейнера, чтобы начать сначала. Это означает, что мы можем указать это так:

// excerpt from docker-compose.yaml

services:
 some-service:
   depends_on: db
 db:
   image: mysql

Здорово, так что решает это или? Нету Нету Нету, держи свои лошади:

Таким образом, в Docker Compose версии 2 раньше было альтернативу, где мы могли бы проверить здоровье службы, если здоровье было хорошим, мы могли бы обрабатывать раскрутить наш контейнер. Это выглядело так:

depends_on:
 db:
   condition: service_healthy

Это означало, что мы можем дождаться базы данных полностью инициализации. Это не было, хотя в версии 3 эта опция ушла. Вот страница Док, которая объясняет, почему Управление запуском и выключением заказа Отказ Гист этого заключается в том, что теперь это зависит от нас, чтобы узнать, когда наша база данных сделана и готова к подключению. Docker предлагает несколько сценариев для этого:

Все эти сценарии имеют одно общее, идея состоит в том, чтобы слушать конкретный хозяин и порт И когда это отвечает обратно, то мы запускаем наше приложение. Так что нам нужно сделать, чтобы сделать эту работу? Ну, давайте выберем одну из этих сценариев, а именно ждать-за-это И давайте перечислите то, что нам нужно сделать:

  • Скопировать Этот скрипт в ваш сервисный контейнер
  • Дайте Права исполнения скрипта
  • поручить Docker-файл для запуска сценария с хостом базы данных и порт в качестве ARGS, а затем для запуска службы после того, как скрипт OKS OKS Это

Давайте начнем с копирования сценария из GitHub в наше Продукт-сервис каталог, так что теперь это выглядит так:

/product-service
  wait-for-it.sh
  Dockerfile
  app.js
  package.json

Теперь давайте откроем Dockerfile и добавьте следующее:

// Dockerfile

FROM node:latest

WORKDIR /app

ENV PORT=3000

COPY . .

RUN npm install

EXPOSE $PORT

COPY wait-for-it.sh /wait-for-it.sh

RUN chmod +x /wait-for-it.sh

Выше мы копируем ждать-for-it.sh Файл к нашему контейнеру и на линии ниже мы даем ему выполнение прав. Стоит отметить, как мы также удаляем Выходная точка от нашего Dockerfile вместо этого мы будем проинструктировать контейнера начать с Docker-Compose.yaml файл. Давайте посмотрим на указанный файл следующий:

// excerpt from docker-compose.yaml

services:
 product-service:
 command: ["/wait-for-it.sh", "db:8002", "--", "npm", "start"]
 db:
 // definition of db service below

Выше мы говорим это, чтобы запустить ждать-for-it.sh файл и как аргумент используют БД: 8002. и после того, как он получает удовлетворительный ответ, то мы можем продолжать работать NPM начать Что затем начнет наш сервис. Это звучит приятно, это будет работать?

Для полного раскрытия давайте покажем наш полный Docker-Compose.yaml файл:

version: '3.3'
  services:
    product-service:
      depends_on:
        - "db"
      build:
        context: ./product-service
      command: ["/wait-for-it.sh", "db:8002", "--", "npm", "start"]
    ports:
      - "8000:3000"
    environment:
      - test=testvalue
      - DATABASE_PASSWORD=complexpassword
      - DATABASE_HOST=db
    volumes:
      - type: bind
      source: ./product-service
      target: /app
    networks:
      - products
   db:
     build: ./product-db
       restart: always
     environment:
       - "MYSQL_ROOT_PASSWORD=complexpassword"
       - "MYSQL_DATABASE=Products"
     ports:
       - "8002:3306"
     networks:
       - products
   inventory-service:
     build:
       context: ./inventory-service
     ports:
       - "8001:3000"
     volumes:
       - my-volume:/var/lib/data

volumes:
 my-volume:

networks:
 products:

Хорошо, так что повторить мы разместили Продукт-сервис и дБ В сети продукты И мы скачали скрипт wait-for-it.sh И мы сказали ему, чтобы запустить, прежде чем наращивать приложение, и в процессе прослушивания хоста и порт базы данных, которая ответила, как только база данных была готова к действию. Это означает, что у нас есть один шаг, который нужно сделать, нам нужно настроить app.js Файл Продукт-сервис Так что давайте откроем этот файл вверх:

// app.js

const express = require('express')
const mysql = require('mysql');
const app = express()
const port = process.env.PORT || 3000;
const test = process.env.test;

let attempts = 0;

const seconds = 1000;

function connect() {
  attempts++;

  console.log('password', process.env.DATABASE_PASSWORD);
  console.log('host', process.env.DATABASE_HOST);
  console.log(`attempting to connect to DB time: ${attempts}`);

 const con = mysql.createConnection({  
   host: process.env.DATABASE_HOST,  
   user: "root",  
   password: process.env.DATABASE_PASSWORD,  
   database: 'Products'  
 });

  con.connect(function (err) {  
   if (err) {  
     console.log("Error", err);  
     setTimeout(connect, 30 * seconds);  
   } else {  
     console.log('CONNECTED!');  
   }

  });

  conn.on('error', function(err) {  
    if(err) {  
      console.log('shit happened :)');  
      connect()  
    }   
  });

}
connect();

app.get('/', (req, res) => res.send(`Hello product service, changed ${test}`))

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

Выше мы можем видеть, что мы определили Подключиться () Метод, который создает связь, вызывая CreateConnection () с объектом как аргумент. Этот входной аргумент должен знать хозяин , Пользователь , пароль и база данных Отказ Это кажется совершенно разумным. Мы также добавляем немного логики к Подключиться () Вызов метода, а именно мы вызываем Setimeate () Это означает, что он попытается сделать другое соединение через 30 секунд. Теперь, потому что мы используем ждать-for-it.sh Эта функциональность на самом деле не нужна, но мы можем полагаться на только код заявки, чтобы мы получили связь. Тем не менее, мы также называем Conn.on («Ошибка») И причина для этого является то, что мы можем потерять связь, и мы должны быть хорошими гражданами и гарантировать, что мы можем вернуть эту связь.

Во всяком случае, мы сделали все в нашей власти, но потому что мы ввели изменения в Dockerfile Давайте восстановим все с Составная сборка А потом давайте все принесем все:

докер

и….

Там есть, Хьюстон у нас есть связь, или как мой друг Барни любит ставить это:

Настройка базы данных — заполните его структурой и данными

Хорошо, может быть, вам интересно, как мы построили сервис DB? Эта часть Docker-Compose.yaml выглядел так:

// docker-compose.yaml

db:
  build: ./product-db
  restart: always
  environment:
    - "MYSQL_ROOT_PASSWORD=complexpassword"
    - "MYSQL_DATABASE=Products"
  ports:
    - "8002:3306"
  networks:
    - products

Я бы вы смотрели на сборку особенно. Мы упомянули в начале этой статьи, что мы можем вытащить готовые изображения баз данных. Это утверждение по-прежнему верно, но путем создания нашего собственного докера для этого мы можем не только указывать базу данных, которую мы хотим, но мы также можем запустить команды, такие как создание структуры базы данных и вставьте данные семян. Давайте посмотрим на каталог Продукт-дБ :

/product-db
  Dockerfile
  init.sql

Хорошо, у нас есть Dockerfile Давайте сначала посмотрим на это:

// Dockerfile

FROM mysql:5.6

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

Мы указываем, что init.sql должны быть скопированы и переименованы в Docker-indressPoint-initdb.d Что означает, что он будет запускать первое, что происходит. Отлично, как насчет содержания init.sql ?

// init.sql

CREATE DATABASE IF NOT EXISTS Products;

# create tables here
# add seed data inserts here

Как видите, это не содержит большого момента, но мы определенно можем расширить его, что важно.

Резюме

Теперь мы приходим полный круг в этой серии, мы объяснили все с самого начала. Основные концепции, основные команды, как иметь дело с объемами и базами данных, а также как быть еще более эффективным с Docker Compose. Эта серия будет продолжаться, конечно, идет глубже и глубже в докере, но это, надеюсь, принесет вас немного на пути. Спасибо за чтение этого далеко.

Докер (5 части серии)

Оригинал: «https://dev.to/azure/dockerfrom-the-beginning-part-v-n2c»