Создаёт свой образ узла

Предпосылки

Обзор

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

Для завершения этого урока вам потребуется следующее:

  • Node.js версии 12.18 или новее. Скачать Node.js

  • Docker работает локально: следуйте инструкциям в скачать и установить docker.

  • IDE или текстовый редактор для редактирования файлов. Мы рекомендуем использовать код Visual Studio.

Образец заявления

Давайте создадим простое приложение Node.js, которое мы можем использовать в качестве примера. Создаёт каталог на локальном компьютере с именем node-docker и выполняет следующие действия, чтобы создать простой REST API.

$ cd [path to your node-docker directory]
$ npm init -y
$ npm install ronin-server ronin-mocks
$ touch server.js

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

Открывает данный рабочий каталог в своей среде IDE и добавляет следующий код в файл server.js.

const ronin = require('ronin-server')
const mocks = require('ronin-mocks')

const server = ronin.server()

server.use('/', mocks.server(server.Router(), false, true))
server.start()

Сервер мокинг называется Ronin.js и по умолчанию будет прослушивать порт 8000. Вы можете отправлять POST-запросы к корневой (/) конечной точке, и любая структура JSON, которую вы отправляете на сервер, будет сохранена в памяти. Вы также можете отправлять запросы GET в ту же конечную точку и получать массив объектов JSON, которые вы ранее отправили POST.

Протестируйте приложение

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

$ node server.js

Чтобы проверяет, правильно ли работает приложение, мы сначала отправим некоторый JSON в API, а затем сделаем запрос GET, чтобы убедиться, что данные были сохранены. Открывает новый терминал и выполняет следующие команды curl:

$ curl --request POST \
  --url http://localhost:8000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing" }'
{"code":"success","payload":[{"msg":"testing","id":"31f23305-f5d0-4b4f-a16f-6f4c8ec93cf1","createDate":"2020-08-28T21:53:07.157Z"}]}

$ curl http://localhost:8000/test
{"code":"success","meta":{"total":1,"count":1},"payload":[{"msg":"testing","id":"31f23305-f5d0-4b4f-a16f-6f4c8ec93cf1","createDate":"2020-08-28T21:53:07.157Z"}]}

Вернитесь к терминалу, где работает наш сервер. Теперь вы должны увидеть следующие запросы в журналах сервера.

2020-XX-31T16:35:08:4260  INFO: POST /test
2020-XX-31T16:35:21:3560  INFO: GET /test

Большой! Мы проверили, что приложение работает. На этом этапе вы завершили локальное тестирование сценария сервера.

Нажмите CTRL-c в сеансе терминала, где работает сервер, чтобы останавливает его.

2021-08-06T12:11:33:8930  INFO: POST /test
2021-08-06T12:11:41:5860  INFO: GET /test
^Cshutting down...

Теперь мы продолжим сборку и запуск приложения в Docker.

Создаёт Dockerfile для Node.js

Затем нам нужно добавить строку в наш Dockerfile, которая сообщает Docker, какой базовый образ мы хотели бы использовать для нашего приложения.

# syntax=docker/dockerfile:1

FROM node:12.18.1

Образы Docker могут наследоваться от других образов. Поэтому вместо создания собственного базового образа мы будем использовать официальный образ Node.js, в котором уже есть все инструменты и пакеты, необходимые для запуска приложения Node.js. Вы можете думать об этом так же, как о наследовании классов в объектно-ориентированном программировании. Например, если бы мы могли создавать образы Docker в JavaScript, мы могли бы написать что-то вроде следующего.

class MyImage extends NodeBaseImage {}

Это создаст класс с именем MyImage, который унаследует функциональность от базового класса NodeBaseImage.

Таким же образом, когда мы используем команду FROM, мы говорим Docker включить в наш образ всю функциональность из образа node:12.18.1.

Примечание

Если вы хотите узнать больше о создании собственных базовых образов, см. статью Создание базовых образов.

Переменная среды NODE_ENV указывает среду, в которой выполняется приложение (обычно это разработка или рабочая среда). Одна из самых простых вещей, которые вы можете сделать для повышения производительности, — установить NODE_ENV на production.

ENV NODE_ENV=production

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

WORKDIR /app

Обычно самое первое, что вы делаете после загрузки проекта, написанного на Node.js, — это устанавливаете пакеты npm. Это гарантирует, что все зависимости вашего приложения будут установлены в каталоге node_modules, где среда выполнения Node сможет их найти.

Прежде чем мы сможем запускает npm install, нам нужно добавить файлы package.json и package-lock.json в наши образы. Для этого мы используем команду COPY. Команда COPY принимает два параметра: src и dest. Первый параметр src сообщает Docker, какие файлы вы хотите копирует в образ. Второй параметр dest сообщает Docker, куда вы хотите копирует данные файлы. Например:

COPY ["<src>", "<dest>"]

Вы можете указывает несколько ресурсов src, разделенных запятой. Например, COPY ["<src1>", "<src2>",..., "<dest>"]. Мы скопируем файлы package.json и package-lock.json в наш рабочий каталог /app.

COPY ["package.json", "package-lock.json*", "./"]

Обратите внимание, что мы копируем не весь рабочий каталог, а только файл package.json. Это позволяет нам использовать кэшированные слои Docker. Когда у нас есть файлы внутри образа, мы можем использовать команду RUN для выполнения команды npm install. Это работает точно так же, как если бы мы запускали npm install локально на нашем компьютере, но на данный раз данные модули Node будут установлены в каталог node_modules внутри нашего образа.

RUN npm install --production

На данный момент у нас есть образ, основанный на версии узла 12.18.1, и мы установили наши зависимости. Следующее, что нам нужно сделать, это добавить наш исходный код в образ. Мы будем использовать команду COPY точно так же, как и с нашими файлами package.json выше.

COPY . .

Команда COPY берет все файлы, находящиеся в текущем каталоге, и копирует их в образ. Теперь все, что нам нужно сделать, это сообщить Docker, какую команду мы хотим запускает, когда наш образ запускается внутри контейнера. Делаем это с помощью команды CMD.

CMD [ "node", "server.js" ]

Вот полный Dockerfile.

# syntax=docker/dockerfile:1

FROM node:12.18.1
ENV NODE_ENV=production

WORKDIR /app

COPY ["package.json", "package-lock.json*", "./"]

RUN npm install --production

COPY . .

CMD [ "node", "server.js" ]

Создаёт файл .dockerignore

Чтобы использовать файл в построить контекст, Dockerfile ссылается на файл, указанный в инструкции, например инструкции COPY. Файл .dockerignore позволяет указывает файлы и каталоги, которые необходимо исключить из контекста сборки. Чтобы повысить производительность сборки, создаёт файл .dockerignore и добавляет в него каталог node_modules:

.dockerignore node_modules

Построить образ

Теперь, когда мы создали наш Dockerfile, давайте создадим наш образ. Для этого воспользуемся командой docker build. Команда docker build создаёт образы Docker из Dockerfile и «контекста». Контекст сборки — это множество файлов, расположенных по указанному пути или URL-адресу. Процесс сборки Docker может получает доступ к любому из файлов, расположенных в контексте.

Команда сборки необязательно принимает флаг --tag. Тег используется для установки имени образа и необязательного тега в формате ‘name:tag’. Мы опустим необязательный «тег», чтобы упростить ситуацию. Если вы не передадите тег, Docker будет использовать «последний» в качестве тега по умолчанию. Вы увидите это в последней строке вывода сборки.

Давайте создадим наш первый образ Docker.

$ docker build --tag node-docker .

[+] Building 93.8s (11/11) FINISHED
 => [internal] load build definition from dockerfile                                          0.1s
 => => transferring dockerfile: 617B                                                          0.0s
 => [internal] load .dockerignore                                                             0.0s
 ...
 => [2/5] WORKDIR /app                                                                        0.4s
 => [3/5] COPY [package.json, package-lock.json*, ./]                                         0.2s
 => [4/5] RUN npm install --production                                                        9.8s
 => [5/5] COPY . .

Просмотр локальных образов

Чтобы увидеть список образов, которые есть на нашем локальном компьютере, у нас есть два варианта. Один из них — использовать CLI, а другой — использовать Docker Desktop. Поскольку в настоящее время мы работаем в терминале, давайте взглянем на список образов с помощью CLI.

Чтобы просмотреть образы, просто запускает команду images.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
node-docker         latest              3809733582bc        About a minute ago   945MB

Ваш точный вывод может отличаться, но вы должны увидеть образ, которое мы только что создали node-docker:latest с тегом latest.

Тэгирование образов

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

Образ состоит из манифеста и списка слоев. Проще говоря, «метка» указывает на комбинацию данных артефактов. Вы можете иметь несколько тегов для образа. Давайте создадим второй тег для созданного нами образа и посмотрим на его слои.

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

$ docker tag node-docker:latest node-docker:v1.0.0

Команда Docker tag создаёт новый тег для образа. Он не создаёт новый образ. Тег указывает на то же образ и является ещё одним способом ссылки на образ.

Теперь запускает команду docker images, чтобы увидеть список наших локальных образов.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
node-docker         latest              3809733582bc        24 minutes ago      945MB
node-docker         v1.0.0              3809733582bc        24 minutes ago      945MB

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

Давайте удалим тег, который мы только что создали. Для этого воспользуемся командой rmi. Команда rmi означает «удаляет образ».

$ docker rmi node-docker:v1.0.0
Untagged: node-docker:v1.0.0

Обратите внимание, что ответ от Docker сообщает нам, что образ не было удалено, а только «не помечено». Убедиться в этом, запустив команду images.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
node-docker         latest              3809733582bc        32 minutes ago      945MB

Наше образ с тегом :v1.0.0 было удалено, но тег node-docker:latest все ещё доступен на нашей машине.

Следующие шаги

В этом модуле мы рассмотрели настройку нашего примера приложения Node, которое мы будем использовать в оставшейся части руководства. Мы также создали файл Dockerfile, который использовали для создания образа Docker. Затем мы рассмотрели тегирование наших образов и удаление образов. В следующем модуле мы рассмотрим, как это сделать:

Запускает образ как контейнер

Обратная связь

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