Создание с помощью Docker
Инженеры-клиенты, инженеры встраиваемых систем и другие инженеры, никогда не работавшие с серверной частью, все равно могут извлечь значительную выгоду из использования контейнеров. В этой части я хотел бы поделиться тем, как я структурирую почти все свои сторонние проекты, чтобы их можно было построить на любой машине, которая установлена make
и docker
установлена.
Мотивация
Гарантия окружающей среды. Несколько сотрудников и сервер непрерывной интеграции (CI) могут быть уверены, что работают в одной и той же среде.
Версионирование среды. Каждому члену команды не нужно создавать образы компоновщика локально. Реестр Docker можно использовать для хранения и версии образов.
Простая настройка рабочей станции/агента сборки. Как упоминалось выше, единственными инструментами, необходимыми для создания такого проекта, являются make
и docker
.
Make
используется здесь не как система сборки проекта, а скорее как удобный инструмент для переноса длинных docker
команд. В рамках статьи мы предполагаем, что проект Rust находится в $(ROOT_DIR)/main
системе cargo
сборки.
Цель Linux
Давайте начнем с простого. Docker — это всегда Linux, поэтому проще всего создать целевую платформу для Linux. Это также идеально подходит для модульного тестирования, если вы пишете Linux или независимое от платформы приложение.
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCE_DIR := $(ROOT_DIR)/main
IMAGE_BUILDER_LINUX := rust:1.61.0
build_linux: builder_linux
@docker run \
--rm \
-v $(SOURCE_DIR):/src \
$(IMAGE_BUILDER_LINUX) \
sh -c 'cd /src && cargo build'
test_linux: builder_linux
@docker run \
--rm \
-v $(SOURCE_DIR):/src \
$(IMAGE_TESTER_LINUX) \
sh -c 'cd /src && cargo test'
builder_linux:
@docker pull $(IMAGE_BUILDER_LINUX)
Теперь простой make build_linux
и make test_linux
должен
- Убедитесь, что образ Docker Builder загружен.
- Запустите сборку/тест с использованием образа
Пользовательские строители
Скорее всего, в конечном итоге вам потребуется настроить образ построителя. Это подразумевало бы создание Dockerfile
и построение изображения с его использованием вместо извлечения изображения, как мы делали выше.
Предположим, что Dockerfile
он находится по адресу $(ROOT_DIR)/image/x
.
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCE_DIR := $(ROOT_DIR)/main
PROJECT_NAME := $(shell basename $(ROOT_DIR))
IMAGE_BUILDER_X := $(PROJECT_NAME)-builder-x
builder_x:
@docker build -t $(IMAGE_BUILDER_X) $(ROOT_DIR)/image/x
Веб-сборка
Позвольте мне воспользоваться этой возможностью, чтобы поделиться некоторыми сценариями для сборки кода Rust в WebAssembly и запуска модульных тестов.
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
SOURCE_DIR := $(ROOT_DIR)/main
PROJECT_NAME := $(shell basename $(ROOT_DIR))
RUST_TARGET_WEB := wasm32-unknown-unknown
IMAGE_BUILDER_WEB := $(PROJECT_NAME)-builder-web
build_web: builder_web
@docker run \
--rm \
-v $(SOURCE_DIR):/src \
$(IMAGE_BUILDER_WEB) \
sh -c 'cd /src && cargo build --target $(RUST_TARGET_WEB)'
test_web: builder_web
@docker run \
--rm \
-v $(SOURCE_DIR):/src \
$(IMAGE_BUILDER_WEB) \
sh -c 'cd /src && CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasmtime_test_runner.sh cargo test --target $(RUST_TARGET_WEB)'
builder_web:
@docker build -t $(IMAGE_BUILDER_WEB) $(ROOT_DIR)/image/web
FROM rust:1.61.0
RUN \
rustup toolchain install '1.61.0-x86_64-unknown-linux-gnu' \
--target 'wasm32-unknown-unknown' \
--component 'rust-std'
RUN curl https://wasmtime.dev/install.sh -sSf | bash
COPY wasmtime_test_runner.sh /usr/bin
VOLUME ["/usr/local/cargo/registry"]
#!/bin/sh
/root/.wasmtime/bin/wasmtime "$@" --invoke main 0 0
Это относительно легко с Rust, потому что rustup
у него есть wasm32
набор инструментов, готовый к загрузке, но с более сложной настройкой кросс-компилятора возможность сделать Dockerfile
описание последовательности установки — спасение.
Мысли
Чем сложнее требуемая настройка сборки, тем больше я рекомендую смотреть на сборку на основе Docker. Настройка рабочей станции для создания проекта, требующего нескольких кросс-компиляторов, особенно при использовании определенных цепочек инструментов, которые могут потребовать некоторого исправления пользователем, может потребовать до нескольких сотен команд bash. Теоретически это можно сделать без контейнеров с помощью bash-скрипта, но с многочисленными предостережениями, в том числе:
- Нулевое состояние должно быть идентичным перед запуском скрипта.
- Обновление настройки сборки при сохранении ее идентичности между рабочими станциями.
- Нет гарантии окружающей среды
- Нет переключения между версиями установки сборки