Выбрать главу

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

Распространение вашего бинарного файла

Простейшей формой распространения было бы добавление двоичного файла, который мы создали в предыдущем разделе, к ресурсам выпуска. Это позволит любому загрузить и запустить его, при условии, что для его комбинации ОС/архитектуры существует двоичный файл. Бинарный файл, который мы создали в предыдущем разделе, будет работать на любом компьютере, использующем ту же базовую ОС и архитектуру, на которой он был скомпилирован — в данном случае x86_64 Linux. Для других архитектур ЦП/ОС, таких как macOS и Windows, потребуются специальные двоичные файлы.

Через Docker

Другой распространенный способ распространения двоичного файла — включение его в образ Docker, который затем можно использовать напрямую. Портативность Crystal упрощает создание таких изображений. Мы также можем использовать многоэтапные сборки для создания двоичного файла в образе, содержащем все необходимые зависимости, а затем извлечь его в более минимальный образ для распространения. Результирующий Dockerfile для этого процесса может выглядеть так:

FROM crystallang/crystaclass="underline" latest-alpine as builder

WORKDIR /app

COPY ./shard.yml ./shard.lock ./

RUN shards install –production

COPY . ./

RUN shards build --static --no-debug --release –production

FROM alpine:latest

WORKDIR /

COPY --from=builder /app/bin/greeter .

ENTRYPOINT ["/greeter"]

Во-первых, мы должны использовать базовый образ Crystal Alpine в качестве основы с псевдонимом builder (подробнее об этом позже). Затем мы должны установить наш WORKDIR, который представляет, на чем будут основываться будущие команды каталога. Далее нам необходимо скопировать shard.yml и shard.lock-файлы для установки любых осколков, не зависящих от разработки. Мы делаем это как отдельные шаги, чтобы они рассматривались как разные слои изображения. Это повышает производительность, поскольку эти шаги будут повторяться только в том случае, если что-то изменится в одном из этих файлов, например, при добавлении или редактировании зависимости.

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

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

Здесь мы должны снова установить наш WORKDIR и скопировать в него двоичный файл. Команда COPY имеет параметр --from, который позволяет указать, какой этап сборки следует использовать в качестве источника. В этом случае мы можем ссылаться на псевдоним builder, который мы определили на первом этапе. Наконец, мы должны установить точку входа изображения в наш двоичный файл, чтобы любые аргументы, передаваемые в изображение, пересылались в сам двоичный файл внутри контейнера.

Теперь, когда мы определили наш Dockerfile, нам нужно создать с его помощью образ. Мы можем сделать это, запустив docker build -t greeter .. Это создаст изображение с тегом Greeter, которое мы затем сможем запустить с помощью docker run --rm greeter --shout George. Поскольку мы определили точку входа изображения в двоичный файл, это будет идентично запуску ./greeter --shout George с локальной копией двоичного файла.

Опция --rm удалит контейнер после его выхода, что полезно при однократных вызовах, чтобы они не накапливались.