Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-platform dockerfiles #84

Merged
merged 3 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/markdown-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ jobs:
steps:
- uses: actions/checkout@v2
- run: |
npm install markdown-link-check
npm install markdown-link-check@3.11.2
find . -type d \( -name node_modules -o -name .github \) -prune -o -type f -name '*.md' -print0 | xargs -0 -n1 node_modules/.bin/markdown-link-check --config ./tools/.markdownlinkcheck.jsonc --quiet
2 changes: 1 addition & 1 deletion Dockerfile.amd64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.74
ARG APP_NAME=pub-sub-service
ARG UID=10001

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.arm64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.74
ARG APP_NAME=pub-sub-service
ARG UID=10001

Expand Down
20 changes: 20 additions & 0 deletions Dockerfile.mosquitto.multi
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
# SPDX-License-Identifier: MIT

# syntax=docker/dockerfile:1

# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/engine/reference/builder/

################################################################################
# Create a stage for building the application.

FROM --platform=$TARGETPLATFORM docker.io/library/eclipse-mosquitto
WORKDIR /mosquitto/config

COPY ./pub-sub-service/src/connectors/mosquitto.conf ./mosquitto.conf

# Expose the port that the mqtt broker listens on.
EXPOSE 1883
115 changes: 115 additions & 0 deletions Dockerfile.multi
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
# SPDX-License-Identifier: MIT

# syntax=docker/dockerfile:1

# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/engine/reference/builder/

################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.74
ARG APP_NAME=pub-sub-service
ARG UID=10001

FROM --platform=$BUILDPLATFORM docker.io/library/rust:${RUST_VERSION} AS build

# Target architecture to cross-compile
ARG TARGETARCH

ARG APP_NAME
WORKDIR /sdv

COPY ./ .

# Check that APP_NAME argument is valid.
RUN /sdv/container/scripts/argument_sanitizer.sh \
--arg-value "${APP_NAME}" \
--regex "^[a-zA-Z_0-9-]+$" || \
( echo "Argument sanitizer failed for ARG 'APP_NAME'"; exit 1 )

# Check that TARGETARCH argument is valid.
RUN /sdv/container/scripts/argument_sanitizer.sh \
--arg-value "${TARGETARCH}" \
--regex "^[a-zA-Z_0-9-]+$" || \
( echo "Argument sanitizer failed for ARG 'TARGETARCH'"; exit 1 )

# Add Build dependencies.
RUN apt update && apt upgrade -y && apt install -y \
cmake \
libssl-dev \
pkg-config \
protobuf-compiler

# Based on the target architecture, add the appropriate build target and build service.
RUN if [ "$TARGETARCH" = "amd64" ]; then \
CARGOARCH="x86_64-unknown-linux-gnu"; \
elif [ "$TARGETARCH" = "arm64" ]; then \
apt install -y gcc-aarch64-linux-gnu; \
CARGOARCH="aarch64-unknown-linux-gnu"; \
else \
echo "Unsupported cross-compile architecture"; \
exit 1; \
fi; \
rustup target add ${CARGOARCH}; \
cargo build --release --target=${CARGOARCH} -p "${APP_NAME}"; \
cp /sdv/target/${CARGOARCH}/release/"${APP_NAME}" /sdv/service

################################################################################
# Create a new stage for running the application that contains the minimal
# runtime dependencies for the application. This often uses a different base
# image from the build stage where the necessary files are copied from the build
# stage.
#
# The example below uses the debian bullseye image as the foundation for running the app.
# By specifying the "bullseye-slim" tag, it will also use whatever happens to be the
# most recent version of that tag when you build your Dockerfile. If
# reproducability is important, consider using a digest
# (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57).
FROM --platform=$TARGETPLATFORM docker.io/library/debian:bullseye-slim AS final
ARG UID

# Copy container scripts.
COPY ./container/scripts/*.sh /sdv/scripts/

# Check that UID argument is valid.
RUN /sdv/scripts/argument_sanitizer.sh \
--arg-value "${UID}" \
--regex "^[0-9]+$" || \
( echo "Argument sanitizer failed for ARG 'UID'"; exit 1 )

# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser

# Create and add user ownership to config directory.
RUN mkdir -p /sdv/.agemo/config
RUN chown appuser /sdv/.agemo/config

# Create mnt directory to copy override configs into.
RUN mkdir -p /mnt/config

USER appuser

WORKDIR /sdv

ENV AGEMO_HOME=/sdv/.agemo

# Copy the executable from the "build" stage.
COPY --from=build /sdv/service /sdv/

# Expose the port that the application listens on.
EXPOSE 50051

# What the container should run when it is started.
CMD ["/sdv/scripts/container_startup.sh"]
2 changes: 1 addition & 1 deletion Dockerfile.samples.amd64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.74
ARG APP_NAME=simple-publisher
ARG UID=10001

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.samples.arm64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.74
ARG APP_NAME=simple-publisher
ARG UID=10001

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile_integrated.amd64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.74
ARG APP_NAME=pub-sub-service
ARG UID=10001

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile_integrated.arm64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.74
ARG APP_NAME=pub-sub-service
ARG UID=10001

Expand Down
118 changes: 118 additions & 0 deletions Dockerfile_integrated.multi
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
# SPDX-License-Identifier: MIT

# syntax=docker/dockerfile:1

# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/engine/reference/builder/

################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.74
ARG APP_NAME=pub-sub-service
ARG UID=10001

FROM --platform=$BUILDPLATFORM docker.io/library/rust:${RUST_VERSION} AS build

# Target architecture to cross-compile
ARG TARGETARCH

ARG APP_NAME
WORKDIR /sdv

COPY ./ .

# Check that APP_NAME argument is valid.
RUN /sdv/container/scripts/argument_sanitizer.sh \
--arg-value "${APP_NAME}" \
--regex "^[a-zA-Z_0-9-]+$" || \
( echo "Argument sanitizer failed for ARG 'APP_NAME'"; exit 1 )

# Check that TARGETARCH argument is valid.
RUN /sdv/container/scripts/argument_sanitizer.sh \
--arg-value "${TARGETARCH}" \
--regex "^[a-zA-Z_0-9-]+$" || \
( echo "Argument sanitizer failed for ARG 'TARGETARCH'"; exit 1 )

# Add Build dependencies.
RUN apt update && apt upgrade -y && apt install -y \
cmake \
libssl-dev \
pkg-config \
protobuf-compiler

# Based on the target architecture, add the appropriate build target and build service.
RUN if [ "$TARGETARCH" = "amd64" ]; then \
CARGOARCH="x86_64-unknown-linux-gnu"; \
elif [ "$TARGETARCH" = "arm64" ]; then \
apt install -y gcc-aarch64-linux-gnu; \
CARGOARCH="aarch64-unknown-linux-gnu"; \
else \
echo "Unsupported cross-compile architecture"; \
exit 1; \
fi; \
rustup target add ${CARGOARCH}; \
cargo build --release --target=${CARGOARCH} -p "${APP_NAME}"; \
cp /sdv/target/${CARGOARCH}/release/"${APP_NAME}" /sdv/service

################################################################################
# Create a new stage for running the application that contains the minimal
# runtime dependencies for the application. This often uses a different base
# image from the build stage where the necessary files are copied from the build
# stage.
#
# The example below uses the debian bullseye image as the foundation for running the app.
# By specifying the "bullseye-slim" tag, it will also use whatever happens to be the
# most recent version of that tag when you build your Dockerfile. If
# reproducability is important, consider using a digest
# (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57).
FROM --platform=$TARGETPLATFORM docker.io/library/debian:bullseye-slim AS final
ARG UID

# Copy container scripts.
COPY ./container/scripts/*.sh /sdv/scripts/

# Check that UID argument is valid.
RUN /sdv/scripts/argument_sanitizer.sh \
--arg-value "${UID}" \
--regex "^[0-9]+$" || \
( echo "Argument sanitizer failed for ARG 'UID'"; exit 1 )

# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser

# Create and add user ownership to config directory.
RUN mkdir -p /sdv/.agemo/config
RUN chown appuser /sdv/.agemo/config

# Create mnt directory to copy override configs into.
RUN mkdir -p /mnt/config

USER appuser

WORKDIR /sdv

ENV AGEMO_HOME=/sdv/.agemo

# Copy the executable from the "build" stage.
COPY --from=build /sdv/service /sdv/

# Copy the "integrated" config to the override config folder and rename it to what agemo expects
COPY --from=build /sdv/config/pub_sub_service_settings.integrated.yaml /sdv/.agemo/config/pub_sub_service_settings.yaml

# Expose the port that the application listens on.
EXPOSE 50051

# What the container should run when it is started.
CMD ["/sdv/scripts/container_startup.sh"]
21 changes: 21 additions & 0 deletions docs/containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ document has instructions for building and running the provided Dockerfiles in
x86-64 architecture.
- [Dockerfile.arm64](../Dockerfile.arm64) - Dockerfile used to build the `Pub Sub Service` for the
aarch64 architecture.
- [Dockerfile.multi](../Dockerfile.multi) - Dockerfile used to build the `Pub Sub Service` for
multiple architectures based on the TARGETARCH argument.
- [Dockerfile_integrated.amd64](../Dockerfile_integrated.amd64) - Dockerfile used to build the
`Pub Sub Service` using
[Chariott Service Discovery](https://github.com/eclipse-chariott/chariott/blob/main/service_discovery/README.md)
Expand All @@ -23,13 +25,21 @@ x86-64 architecture.
[Chariott Service Discovery](https://github.com/eclipse-chariott/chariott/blob/main/service_discovery/README.md)
with the [integrated configuration](../config/pub_sub_service_settings.integrated.yaml) for the
aarch64 architecture.
- [Dockerfile_integrated.multi](../Dockerfile_integrated.multi) - Dockerfile used to build the
`Pub Sub Service` using
[Chariott Service Discovery](https://github.com/eclipse-chariott/chariott/blob/main/service_discovery/README.md)
with the [integrated configuration](../config/pub_sub_service_settings.integrated.yaml) for
multiple architectures based on the TARGETARCH argument.

#### Mosquitto MQTT Broker

- [Dockerfile.mosquitto.amd64](../Dockerfile.mosquitto.amd64) - Dockerfile used to build the
`Mosquitto MQTT Broker` with the appropriate configuration for the x86-64 architecture.
- [Dockerfile.mosquitto.arm64](../Dockerfile.mosquitto.arm64) - Dockerfile used to build the
`Mosquitto MQTT Broker` with the appropriate configuration for the aarch64 architecture.
- [Dockerfile.mosquitto.multi](../Dockerfile.mosquitto.multi) - Dockerfile used to build the
`Mosquitto MQTT Broker` with the appropriate configuration for multiple architectures based on the
TARGETARCH argument.

#### Sample Applications

Expand Down Expand Up @@ -73,6 +83,17 @@ Dockerfile:
>Note: The build arg `APP_NAME` needs to be passed in for all sample applications to build the
correct sample.

Or to build a multi-platform image for `pub-sub-service` project and push it to a container
registry:
You must first create a new builder using the docker-container driver, which gives you access
to more complex features like multi-platform build. See more information here:
[multi-platform builds.](https://docs.docker.com/build/building/multi-platform/#cross-compilation)

```shell
docker buildx create --name multibuilder --driver docker-container --use
docker buildx build --platform=linux/amd64,linux/arm64 -f Dockerfile.multi -t <container_registry>/pub_sub_service_multi --push .
```

1. Once the container has been built, start the container in interactive mode with the following
command in the project root directory:

Expand Down
Loading