Простейшей формой распространения было бы добавление двоичного файла, который мы создали в предыдущем разделе, к ресурсам выпуска. Это позволит любому загрузить и запустить его, при условии, что для его комбинации ОС/архитектуры существует двоичный файл. Бинарный файл, который мы создали в предыдущем разделе, будет работать на любом компьютере, использующем ту же базовую ОС и архитектуру, на которой он был скомпилирован — в данном случае x86_64 Linux. Для других архитектур ЦП/ОС, таких как macOS и Windows, потребуются специальные двоичные файлы.
Через Docker
Другой распространенный способ распространения двоичного файла — включение его в образ Docker, который затем можно использовать напрямую. Портативность Crystal упрощает создание таких изображений. Мы также можем использовать многоэтапные сборки для создания двоичного файла в образе, содержащем все необходимые зависимости, а затем извлечь его в более минимальный образ для распространения. Результирующий Dockerfile для этого процесса может выглядеть так:
FROM crystallang/crystal: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
, который представляет, на чем будут основываться будущие команды каталога. Далее нам необходимо скопировать
Наконец, в качестве последней команды на этом этапе сборки мы создаем статический двоичный файл выпуска, который в конечном итоге будет создан в
Начало второго этапа сборки начинается с использования в качестве базовой последней версии Alpine. Поскольку двоичный файл является статическим, мы могли бы использовать царапину в качестве основы. Тем не менее, мне нравится использовать Alpine, поскольку он уже имеет довольно минимальный размер, но также предоставляет вам менеджер пакетов на случай, если вам все еще понадобится какое-то подмножество зависимостей, что в большинстве случаев вам понадобится.
Здесь мы должны снова установить наш WORKDIR
и скопировать в него двоичный файл. Команда COPY
имеет параметр --from
, который позволяет указать, какой этап сборки следует использовать в качестве источника. В этом случае мы можем ссылаться на псевдоним builder
, который мы определили на первом этапе. Наконец, мы должны установить точку входа изображения в наш двоичный файл, чтобы любые аргументы, передаваемые в изображение, пересылались в сам двоичный файл внутри контейнера.
Теперь, когда мы определили наш Dockerfile, нам нужно создать с его помощью образ. Мы можем сделать это, запустив docker build -t greeter .
. Это создаст изображение с тегом Greeter, которое мы затем сможем запустить с помощью docker run --rm greeter --shout George
. Поскольку мы определили точку входа изображения в двоичный файл, это будет идентично запуску ./greeter --shout George
с локальной копией двоичного файла.
Опция --rm
удалит контейнер после его выхода, что полезно при однократных вызовах, чтобы они не накапливались.
Также возможно извлечь двоичный файл из контейнера. Но прежде чем мы сможем это сделать, нам нужно получить идентификатор контейнера. Вы можете просмотреть существующие контейнеры с помощью команды docker ps -a
. Если вы запустите наш образ без флага --rm
, вы увидите вышедший из этого вызова контейнер. Если у вас в настоящее время нет существующего контейнера, его можно создать с помощью команды docker create greetinger
, которая возвращает идентификатор контейнера, который мы можем использовать на следующем шаге.