From 4f449fc554efd7536bb0e561592c8fa0ab0577ec Mon Sep 17 00:00:00 2001 From: Devin Kelley <105753233+devkelley@users.noreply.github.com> Date: Tue, 28 Nov 2023 16:54:26 -0800 Subject: [PATCH 1/7] Add/Update Dockerfiles to provide arm64 support --- .cargo/config.toml | 4 + Cargo.lock | 10 + Dockerfile | 2 +- Dockerfile.arm64 | 95 +++++++++ Dockerfile.mosquitto | 19 ++ Dockerfile.mosquitto.arm64 | 19 ++ Dockerfile.samples | 89 ++++++++ Dockerfile.samples.arm64 | 92 ++++++++ README.md | 124 +---------- container/template/docker.env | 9 - container/template/podman.env | 9 - docs/containers.md | 199 ++++++++++++++++++ pub-sub-service/Cargo.toml | 4 +- .../src/connectors/chariott_connector.rs | 5 +- .../src/connectors/mosquitto_connector.rs | 12 +- pub-sub-service/src/load_config.rs | 22 -- pub-sub-service/src/topic_manager.rs | 7 +- samples/README.md | 11 + samples/connectors/mqtt-five/Cargo.toml | 5 +- 19 files changed, 554 insertions(+), 183 deletions(-) create mode 100644 Dockerfile.arm64 create mode 100644 Dockerfile.mosquitto create mode 100644 Dockerfile.mosquitto.arm64 create mode 100644 Dockerfile.samples create mode 100644 Dockerfile.samples.arm64 delete mode 100644 container/template/docker.env delete mode 100644 container/template/podman.env create mode 100644 docs/containers.md diff --git a/.cargo/config.toml b/.cargo/config.toml index 7b38eb0..4fd7cf9 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -5,3 +5,7 @@ [env] AGEMO_HOME = { value = ".agemo", relative = true } AGEMO_SAMPLES_HOME = { value = ".agemo-samples", relative = true } + +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" +rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lgcc" ] diff --git a/Cargo.lock b/Cargo.lock index 50e4d48..fc48c2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1141,6 +1141,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl-src" +version = "300.1.6+3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.96" @@ -1149,6 +1158,7 @@ checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] diff --git a/Dockerfile b/Dockerfile index d0b02d1..f616ee2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,7 @@ RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ } # Build the application with the 'containerize' feature. -RUN cargo build --features containerize --release -p "${APP_NAME}" +RUN cargo build --release -p "${APP_NAME}" # Copy the built application to working directory. RUN cp ./target/release/"${APP_NAME}" /sdv/service diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 new file mode 100644 index 0000000..072721a --- /dev/null +++ b/Dockerfile.arm64 @@ -0,0 +1,95 @@ +# 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.72.1 +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME=pub-sub-service +WORKDIR /sdv + +COPY ./ . + +# Add Build dependencies. +RUN apt update && apt upgrade -y && apt install -y \ + cmake \ + libssl-dev \ + pkg-config \ + protobuf-compiler \ + gcc-aarch64-linux-gnu + +# Check that APP_NAME argument is valid. +RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ +[ "$sanitized" = "${APP_NAME}" ] || { \ + echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ + exit 1; \ +} + +RUN rustup target add aarch64-unknown-linux-gnu + +# Build the application with the 'containerize' feature. +RUN cargo build --release --target=aarch64-unknown-linux-gnu -p "${APP_NAME}" + +# Copy the built application to working directory. +RUN cp ./target/aarch64-unknown-linux-gnu/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 docker.io/arm64v8/debian:bullseye-slim AS final + +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user +ARG UID=10001 +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 startup script. +COPY --from=build /sdv/container_startup.sh /sdv/container_startup.sh + +# Copy default configs. +COPY --from=build /sdv/.agemo/config/ /sdv/.agemo/config/ + +# Expose the port that the application listens on. +EXPOSE 50051 + +# What the container should run when it is started. +CMD ["/sdv/container_startup.sh"] diff --git a/Dockerfile.mosquitto b/Dockerfile.mosquitto new file mode 100644 index 0000000..3905c3e --- /dev/null +++ b/Dockerfile.mosquitto @@ -0,0 +1,19 @@ +# 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 docker.io/library/eclipse-mosquitto +WORKDIR /mosquitto/config + +COPY ./pub-sub-service/src/connectors/mosquitto.conf ./mosquitto.conf + +EXPOSE 1883 \ No newline at end of file diff --git a/Dockerfile.mosquitto.arm64 b/Dockerfile.mosquitto.arm64 new file mode 100644 index 0000000..c55b9e5 --- /dev/null +++ b/Dockerfile.mosquitto.arm64 @@ -0,0 +1,19 @@ +# 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 docker.io/arm64v8/eclipse-mosquitto +WORKDIR /mosquitto/config + +COPY ./pub-sub-service/src/connectors/mosquitto.conf ./mosquitto.conf + +EXPOSE 1883 \ No newline at end of file diff --git a/Dockerfile.samples b/Dockerfile.samples new file mode 100644 index 0000000..c2daa65 --- /dev/null +++ b/Dockerfile.samples @@ -0,0 +1,89 @@ +# 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.72.1 +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME=simple-publisher +WORKDIR /sdv + +COPY ./ . + +# Add Build dependencies. +RUN apt update && apt upgrade -y && apt install -y \ + cmake \ + libssl-dev \ + pkg-config \ + protobuf-compiler + +# Check that APP_NAME argument is valid. +RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ +[ "$sanitized" = "${APP_NAME}" ] || { \ + echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ + exit 1; \ +} + +# Build the application with the 'containerize' feature. +RUN cargo build --release -p "${APP_NAME}" + +# Copy the built application to working directory. +RUN cp ./target/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 docker.io/library/debian:bullseye-slim AS final + +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user +ARG UID=10001 +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_SAMPLES_HOME=/sdv/.agemo + +# Copy the executable from the "build" stage. +COPY --from=build /sdv/service /sdv/ + +# Copy startup script. +COPY --from=build /sdv/container_startup.sh /sdv/container_startup.sh + +# Copy default configs. +COPY --from=build /sdv/.agemo-samples/config/ /sdv/.agemo/config/ + +# What the container should run when it is started. +CMD ["/sdv/container_startup.sh"] diff --git a/Dockerfile.samples.arm64 b/Dockerfile.samples.arm64 new file mode 100644 index 0000000..3f412f5 --- /dev/null +++ b/Dockerfile.samples.arm64 @@ -0,0 +1,92 @@ +# 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.72.1 +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME=simple-publisher +WORKDIR /sdv + +COPY ./ . + +# Add Build dependencies. +RUN apt update && apt upgrade -y && apt install -y \ + cmake \ + libssl-dev \ + pkg-config \ + protobuf-compiler \ + gcc-aarch64-linux-gnu + +# Check that APP_NAME argument is valid. +RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ +[ "$sanitized" = "${APP_NAME}" ] || { \ + echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ + exit 1; \ +} + +RUN rustup target add aarch64-unknown-linux-gnu + +# Build the application with the 'containerize' feature. +RUN cargo build --release --target=aarch64-unknown-linux-gnu -p "${APP_NAME}" + +# Copy the built application to working directory. +RUN cp ./target/aarch64-unknown-linux-gnu/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 docker.io/arm64v8/debian:bullseye-slim AS final + +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user +ARG UID=10001 +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_SAMPLES_HOME=/sdv/.agemo + +# Copy the executable from the "build" stage. +COPY --from=build /sdv/service /sdv/ + +# Copy startup script. +COPY --from=build /sdv/container_startup.sh /sdv/container_startup.sh + +# Copy default configs. +COPY --from=build /sdv/.agemo-samples/config/ /sdv/.agemo/config/ + +# What the container should run when it is started. +CMD ["/sdv/container_startup.sh"] diff --git a/README.md b/README.md index 2db0eaf..994f0ad 100644 --- a/README.md +++ b/README.md @@ -197,127 +197,11 @@ see more full featured examples in ## Running in a Container -Below are the steps for running the service in a container. Note that the default configuration -files used by the containerized service are cloned from [.agemo/config](.agemo/config/) defined in -the project's root. +Please refer to the following links for how to build and run the service in a OCI container: -### Docker - -#### Prequisites - -[Install Docker](https://docs.docker.com/engine/install/) - -#### Running in Docker - -To run the service in a Docker container: - -1. Copy the [docker.env](./container/template/docker.env) template into the project root directory. -The file sets two environment variables, 'HOST_GATEWAY' and 'LOCALHOST_ALIAS', where 'HOST_GATEWAY' -is the DNS name used by the container to represent the localhost address and 'LOCALHOST_ALIAS' is -the localhost address used in the service's configuration settings. This file should already be set -up with out any modification needed. From the project root directory, the file can be copied with: - - ```shell - cp ./container/template/docker.env . - ``` - -1. Run the following command in the project root directory to build the docker container from the -Dockerfile: - - ```shell - docker build -t pub_sub_service -f Dockerfile . - ``` - -1. Once the container has been built, start the container in interactive mode with the following -command in the project root directory: - - ```shell - docker run --name pub_sub_service -p 50051:50051 --env-file=docker.env --add-host=host.docker.internal:host-gateway -it --rm pub_sub_service - ``` - -1. To detach from the container, enter: - - Ctrl + p, Ctrl + q - -1. To stop the container, enter: - - ```shell - docker stop pub_sub_service - ``` - -#### Running in Docker with overriden configuration - -Follow the steps in [Running in Docker](#running-in-docker) to build the container. - -1. To run the container with overriden configuration, create your config file and set an -environment variable called CONFIG_HOME to the path to the config file: - - ```shell - export CONFIG_HOME={path to directory containing config file} - ``` - -1. Then run the container with the following command: - - ```shell - docker run -v ${CONFIG_HOME}:/mnt/config --name pub_sub_service -p 50051:50051 --env-file=docker.env --add-host=host.docker.internal:host-gateway -it --rm pub_sub_service - ``` - -### Podman - -#### Prequisites - -[Install Podman](https://podman.io/docs/installation) - -#### Running in Podman - -To run the service in a Podman container: - -1. Copy the [podman.env](./container/template/podman.env) template into the project root directory. -The file sets two environment variables, 'HOST_GATEWAY' and 'LOCALHOST_ALIAS', where 'HOST_GATEWAY' -is the DNS name used by the container to represent the localhost address and 'LOCALHOST_ALIAS' is -the localhost address used in the service's configuration settings. This file should already be set -up with out any modification needed. From the project root directory, the file can be copied with: - - ```shell - cp ./container/template/podman.env . - ``` - -1. Run the following command in the project root directory to build the podman container from the -Dockerfile: - - ```shell - podman build -t pub_sub_service:latest -f Dockerfile . - ``` - -1. Once the container has been built, start the container with the following command in the project -root directory: - - ```shell - podman run -p 50051:50051 --env-file=podman.env --network=slirp4netns:allow_host_loopback=true localhost/pub_sub_service - ``` - -1. To stop the container, run: - - ```shell - podman ps -f ancestor=localhost/pub_sub_service:latest --format="{{.Names}}" | xargs podman stop - ``` - -#### Running in Podman with overriden configuration - -Follow the steps in [Running in Podman](#running-in-podman) to build the container. - -1. To run the container with overriden configuration, create your config file and set an -environment variable called CONFIG_HOME to the path to the config file: - - ```shell - export CONFIG_HOME={path to directory containing config file} - ``` - -1. Then run the container with the following command: - - ```shell - podman run --mount=type=bind,src=${CONFIG_HOME},dst=/mnt/config,ro=true -p 50051:50051 --env-file=podman.env --network=slirp4netns:allow_host_loopback=true localhost/pub_sub_service - ``` +- [Provided Dockerfiles](./docs/containers.md#dockerfiles) +- [Docker Containers](./docs/containers.md#docker-containers) +- [Podman Containers](./docs/containers.md#podman-containers) ## Trademarks diff --git a/container/template/docker.env b/container/template/docker.env deleted file mode 100644 index 56bafc6..0000000 --- a/container/template/docker.env +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. -# SPDX-License-Identifier: MIT - -# DNS name used by the container to communicate with host. -HOST_GATEWAY=host.docker.internal - -# Alias for localhost to be replaced by HOST_GATEWAY if run in a container. -LOCALHOST_ALIAS=0.0.0.0 diff --git a/container/template/podman.env b/container/template/podman.env deleted file mode 100644 index 1abc4a3..0000000 --- a/container/template/podman.env +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. -# SPDX-License-Identifier: MIT - -# DNS name used by the container to communicate with host. -HOST_GATEWAY=host.containers.internal - -# Alias for localhost to be replaced by HOST_GATEWAY if run in a container. -LOCALHOST_ALIAS=0.0.0.0 diff --git a/docs/containers.md b/docs/containers.md new file mode 100644 index 0000000..8f7c231 --- /dev/null +++ b/docs/containers.md @@ -0,0 +1,199 @@ +## Containers + +### Dockerfiles + +This repository currently provides the following Dockerfiles: + +#### Pub Sub Service + +- [Dockerfile](../Dockerfile) - Dockerfile used to build the `Pub Sub Service`. +- [Dockerfile.arm64](../Dockerfile.arm64) - Dockerfile used to build the `Pub Sub Service` for the +aarch64 architecture. + +>Note: The default configuration files are cloned from [.agemo/config](../.agemo/config/), defined +in the project's root. + +#### Mosquitto MQTT Broker + +- [Dockerfile.mosquitto](../Dockerfile.mosquitto) - Dockerfile used to build the +`Mosquitto MQTT Broker` with the appropriate configuration. +- [Dockerfile.mosquitto.arm64](../Dockerfile.mosquitto.arm64) - Dockerfile used to build the +`Mosquitto MQTT Broker` with the appropriate configuration for the aarch64 architecture. + +#### Sample Applications + +- [Dockerfile.samples](../Dockerfile.samples) - Dockerfile used to build one of the sample +applications. +- [Dockerfile.samples.arm64](../Dockerfile.samples.arm64) - Dockerfile used to build one of the +sample applications for the aarch64 architecture. + +>Note: The samples default configuration files are cloned from +[.agemo-samples/config](../.agemo-samples/config/), defined in the project's root. + +### Docker Containers + +#### Prequisites + +[Install Docker](https://docs.docker.com/engine/install/) + +#### Running in Docker + +To run the service in a Docker container: + +1. Run the following command in the project root directory to build the docker container from the +Dockerfile: + + ```shell + docker build -t -f (optional: --build-arg=APP_NAME=) . + ``` + + For example, to build an image for the `pub-sub-service` project: + + ```shell + docker build -t pub_sub_service -f Dockerfile . + ``` + + Or to build an image for the `chariott-publisher` sample for aarch64: + + ```shell + docker build -t chariott_publisher -f Dockerfile.samples.arm64 --build-arg=APP_NAME=chariott-publisher . + ``` + + >Note: The build arg `APP_NAME` needs to be passed in for all sample applications to build the + correct sample. + +1. Once the container has been built, start the container in interactive mode with the following +command in the project root directory: + + ```shell + docker run --name --network=host -it --rm + ``` + + For example, to run the `pub-sub-service` image built in step 1: + + ```shell + docker run --name pub_sub_service --network=host -it --rm pub_sub_service + ``` + + >Note: A custom network is recommended when using a container for anything but testing. + +1. To detach from the container, enter: + + Ctrl + p, Ctrl + q + +1. To stop the container, enter: + + ```shell + docker stop + ``` + + For example, to stop the `pub_sub_service` container started in step 2: + + ```shell + docker stop pub_sub_service + ``` + +#### Running in Docker with overridden configuration + +Follow the steps in [Running in Docker](#running-in-docker) to build the container. + +1. To run the container with overridden configuration, create your config file and set an +environment variable called CONFIG_HOME to the path to the config file: + + ```shell + export CONFIG_HOME={path to directory containing config file} + ``` + +1. Then run the container with the following command: + + ```shell + docker run -v ${CONFIG_HOME}:/mnt/config --name --network=host -it --rm + ``` + + For example, to run the `pub_sub_service` image with overridden configuration: + + ```shell + docker run -v ${CONFIG_HOME}:/mnt/config --name pub_sub_service --network=host -it --rm pub_sub_service + ``` + +### Podman Containers + +#### Prequisites + +[Install Podman](https://podman.io/docs/installation) + +#### Running in Podman + +To run the service in a Podman container: + +1. Run the following command in the project root directory to build the podman container from the +Dockerfile: + + ```shell + podman build -t -f . + ``` + + For example, to build an image for the `pub-sub-service` project: + + ```shell + podman build -t pub_sub_service -f Dockerfile . + ``` + + Or to build an image for the `chariott-publisher` sample for aarch64: + + ```shell + podman build -t chariott_publisher -f Dockerfile.samples.arm64 --build-arg=APP_NAME=chariott-publisher . + ``` + + >Note: The build arg `APP_NAME` needs to be passed in for all sample applications to build the + correct sample. + +1. Once the container has been built, start the container with the following command in the project +root directory: + + ```shell + podman run --network=host + ``` + + For example, to run the `pub-sub-service` image built in step 1: + + ```shell + podman run --network=host pub_sub_service + ``` + + >Note: A custom network is recommended when using a container for anything but testing. + +1. To stop the container, run: + + ```shell + podman ps -f ancestor= --format="{{.Names}}" | xargs podman stop + ``` + + For example, to stop the `pub_sub_service` container started in step 2: + + ```shell + podman ps -f ancestor=localhost/pub_sub_service:latest --format="{{.Names}}" | xargs podman stop + ``` + +#### Running in Podman with overridden configuration + +Follow the steps in [Running in Podman](#running-in-podman) to build the container. + +1. To run the container with overridden configuration, create your config file and set an +environment variable called CONFIG_HOME to the path to the config file: + + ```shell + export CONFIG_HOME={path to directory containing config file} + ``` + +1. Then run the container with the following command: + + ```shell + podman run --mount=type=bind,src=${CONFIG_HOME},dst=/mnt/config,ro=true --network=host + ``` + + For example, to run the `pub_sub_service` image with overridden configuration: + + ```shell + podman run --mount=type=bind,src=${CONFIG_HOME},dst=/mnt/config,ro=true --network=host pub_sub_service + ``` diff --git a/pub-sub-service/Cargo.toml b/pub-sub-service/Cargo.toml index 9faec05..8a3380f 100644 --- a/pub-sub-service/Cargo.toml +++ b/pub-sub-service/Cargo.toml @@ -28,5 +28,5 @@ url = { workspace = true } uuid = { workspace = true, features = [ "v4", "fast-rng", "macro-diagnostics"] } yaml-rust = { workspace = true } -[features] -containerize = [] +[target.'cfg(target_arch = "aarch64")'.dependencies] +paho-mqtt = { workspace = true, features = ["vendored-ssl"] } diff --git a/pub-sub-service/src/connectors/chariott_connector.rs b/pub-sub-service/src/connectors/chariott_connector.rs index 015ae08..01606c0 100644 --- a/pub-sub-service/src/connectors/chariott_connector.rs +++ b/pub-sub-service/src/connectors/chariott_connector.rs @@ -13,8 +13,6 @@ use proto::{ service_registry::v1::{RegisterRequest, ServiceMetadata}, }; -use crate::load_config::get_uri; - type ChariottClient = ServiceRegistryClient; /// Object that contains the necessary information for identifying a specific service. @@ -39,10 +37,9 @@ pub async fn connect_to_chariott_with_retry( ) -> Result> { let mut client_opt: Option = None; let mut reason = String::new(); - let uri = get_uri(chariott_uri)?; while client_opt.is_none() { - client_opt = match ServiceRegistryClient::connect(uri.clone()).await { + client_opt = match ServiceRegistryClient::connect(chariott_uri.to_owned()).await { Ok(client) => Some(client), Err(e) => { let status = Status::from_error(Box::new(e)); diff --git a/pub-sub-service/src/connectors/mosquitto_connector.rs b/pub-sub-service/src/connectors/mosquitto_connector.rs index 5989164..228535b 100644 --- a/pub-sub-service/src/connectors/mosquitto_connector.rs +++ b/pub-sub-service/src/connectors/mosquitto_connector.rs @@ -14,10 +14,7 @@ use log::{error, info, warn}; use paho_mqtt::{self as mqtt, MQTT_VERSION_5}; use std::{process, sync::mpsc}; -use crate::{ - load_config::get_uri, - pubsub_connector::{self, MonitorMessage, PubSubAction, PubSubConnector}, -}; +use crate::pubsub_connector::{self, MonitorMessage, PubSubAction, PubSubConnector}; /// Mosquitto broker's reserved topic for subscribe related notifications. const SUBSCRIBE: &str = "$SYS/broker/log/M/subscribe"; @@ -39,13 +36,8 @@ impl MqttFiveBrokerConnector { /// * `client_id` - Id used when creating a new mqtt client. /// * `broker_uri` - The uri of the broker that the client is connecting to. fn new(client_id: String, broker_uri: String) -> Self { - let host = get_uri(&broker_uri).unwrap_or_else(|e| { - error!("Error creating the client: {e:?}"); - process::exit(1); - }); - let create_opts = mqtt::CreateOptionsBuilder::new() - .server_uri(host) + .server_uri(broker_uri) .client_id(client_id) .finalize(); diff --git a/pub-sub-service/src/load_config.rs b/pub-sub-service/src/load_config.rs index 0544f7c..c1f1f80 100644 --- a/pub-sub-service/src/load_config.rs +++ b/pub-sub-service/src/load_config.rs @@ -13,28 +13,6 @@ use serde_derive::{Deserialize, Serialize}; const CONFIG_FILE_NAME: &str = "pub_sub_service_settings"; const CONSTANTS_FILE_NAME: &str = "constants"; -/// If feature 'containerize' is set, will modify a localhost uri to point to container's localhost -/// DNS alias. Otherwise, returns the uri as a String. -/// -/// # Arguments -/// * `uri` - The uri to potentially modify. -pub fn get_uri(uri: &str) -> Result> { - #[cfg(feature = "containerize")] - let uri = { - // Container env variable names. - const HOST_GATEWAY_ENV_VAR: &str = "HOST_GATEWAY"; - const LOCALHOST_ALIAS_ENV_VAR: &str = "LOCALHOST_ALIAS"; - - // Return an error if container env variables are not set. - let host_gateway = env::var(HOST_GATEWAY_ENV_VAR)?; - let localhost_alias = env::var(LOCALHOST_ALIAS_ENV_VAR)?; // DevSkim: ignore DS162092 - - uri.replace(&localhost_alias, &host_gateway) // DevSkim: ignore DS162092 - }; - - Ok(uri.to_string()) -} - /// Object that contains constants used for establishing connection between services. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CommunicationConstants { diff --git a/pub-sub-service/src/topic_manager.rs b/pub-sub-service/src/topic_manager.rs index dfb2d9b..f3a8824 100644 --- a/pub-sub-service/src/topic_manager.rs +++ b/pub-sub-service/src/topic_manager.rs @@ -19,10 +19,7 @@ use proto::publisher::v1::{ }; use tonic::Request; -use crate::{ - load_config::get_uri, - pubsub_connector::{MonitorMessage, PubSubAction}, -}; +use crate::pubsub_connector::{MonitorMessage, PubSubAction}; /// Metadata relevant to a dynamic topic. #[derive(Clone, Debug, PartialEq)] @@ -297,7 +294,7 @@ impl TopicManager { } // Get information from publisher client - let uri = get_uri(&action_metadata.uri)?; + let uri = action_metadata.uri.clone(); let mut pub_client = PublisherCallbackClient::connect(uri).await?; let request = Request::new(ManageTopicRequest { diff --git a/samples/README.md b/samples/README.md index 8b1ebbb..beed2a9 100644 --- a/samples/README.md +++ b/samples/README.md @@ -162,3 +162,14 @@ until the Pub Sub Service registers. All services will retry every 5 seconds when attempting connection to Chariott until the Chariott service is up and running. + +## Running the samples in a Container + +Please refer to [containers.md](../docs/containers.md) for instructions on how to build and run the +sample applications. All the samples use the same Dockerfile so the build arg `APP_NAME` will need +to be set when building the sample application image. For the Chariott-enabled samples, one may +need to override the configuration. Please see +[Running in Docker with Overridden Configuration](../docs/containers.md#running-in-docker-with-overridden-configuration) +and +[Running in Podman with Overridden Configuration](../docs/containers.md#running-in-podman-with-overridden-configuration) +for more information. diff --git a/samples/connectors/mqtt-five/Cargo.toml b/samples/connectors/mqtt-five/Cargo.toml index c66b859..243ded9 100644 --- a/samples/connectors/mqtt-five/Cargo.toml +++ b/samples/connectors/mqtt-five/Cargo.toml @@ -11,4 +11,7 @@ license = "MIT" [dependencies] async-trait = { workspace = true } log = { workspace = true } -paho-mqtt = { workspace = true } \ No newline at end of file +paho-mqtt = { workspace = true } + +[target.'cfg(target_arch = "aarch64")'.dependencies] +paho-mqtt = { workspace = true, features = ["vendored-ssl"] } From b420913f0c2494abbc41c38c3d37a9ca478ad4fa Mon Sep 17 00:00:00 2001 From: Devin Kelley <105753233+devkelley@users.noreply.github.com> Date: Thu, 30 Nov 2023 12:21:35 -0800 Subject: [PATCH 2/7] Add arg_sanitizer script, update dockerfiles to use script, move args to top of file, removed old comments --- Dockerfile => Dockerfile.amd64 | 36 ++++++----- Dockerfile.arm64 | 32 ++++++---- ...le.mosquitto => Dockerfile.mosquitto.amd64 | 2 +- Dockerfile.mosquitto.arm64 | 3 +- ...erfile.samples => Dockerfile.samples.amd64 | 32 ++++++---- Dockerfile.samples.arm64 | 32 ++++++---- container/scripts/argument_sanitizer.sh | 61 +++++++++++++++++++ .../scripts/container_startup.sh | 2 +- docs/containers.md | 22 ++++--- 9 files changed, 160 insertions(+), 62 deletions(-) rename Dockerfile => Dockerfile.amd64 (82%) rename Dockerfile.mosquitto => Dockerfile.mosquitto.amd64 (98%) rename Dockerfile.samples => Dockerfile.samples.amd64 (82%) create mode 100755 container/scripts/argument_sanitizer.sh rename container_startup.sh => container/scripts/container_startup.sh (88%) diff --git a/Dockerfile b/Dockerfile.amd64 similarity index 82% rename from Dockerfile rename to Dockerfile.amd64 index f616ee2..7700aa5 100644 --- a/Dockerfile +++ b/Dockerfile.amd64 @@ -12,12 +12,21 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 -FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME=pub-sub-service +ARG UID=10001 + +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +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 ) + # Add Build dependencies. RUN apt update && apt upgrade -y && apt install -y \ cmake \ @@ -25,14 +34,7 @@ RUN apt update && apt upgrade -y && apt install -y \ pkg-config \ protobuf-compiler -# Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} - -# Build the application with the 'containerize' feature. +# Build the application. RUN cargo build --release -p "${APP_NAME}" # Copy the built application to working directory. @@ -50,10 +52,19 @@ RUN cp ./target/release/"${APP_NAME}" /sdv/service # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM 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 -ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ @@ -79,9 +90,6 @@ ENV AGEMO_HOME=/sdv/.agemo # Copy the executable from the "build" stage. COPY --from=build /sdv/service /sdv/ -# Copy startup script. -COPY --from=build /sdv/container_startup.sh /sdv/container_startup.sh - # Copy default configs. COPY --from=build /sdv/.agemo/config/ /sdv/.agemo/config/ @@ -89,4 +97,4 @@ COPY --from=build /sdv/.agemo/config/ /sdv/.agemo/config/ EXPOSE 50051 # What the container should run when it is started. -CMD ["/sdv/container_startup.sh"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 072721a..8843814 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -12,8 +12,11 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 -FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME=pub-sub-service +ARG UID=10001 + +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME WORKDIR /sdv COPY ./ . @@ -27,15 +30,14 @@ RUN apt update && apt upgrade -y && apt install -y \ gcc-aarch64-linux-gnu # Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} +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 ) RUN rustup target add aarch64-unknown-linux-gnu -# Build the application with the 'containerize' feature. +# Build the application. RUN cargo build --release --target=aarch64-unknown-linux-gnu -p "${APP_NAME}" # Copy the built application to working directory. @@ -53,10 +55,19 @@ RUN cp ./target/aarch64-unknown-linux-gnu/release/"${APP_NAME}" /sdv/service # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM docker.io/arm64v8/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 -ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ @@ -82,9 +93,6 @@ ENV AGEMO_HOME=/sdv/.agemo # Copy the executable from the "build" stage. COPY --from=build /sdv/service /sdv/ -# Copy startup script. -COPY --from=build /sdv/container_startup.sh /sdv/container_startup.sh - # Copy default configs. COPY --from=build /sdv/.agemo/config/ /sdv/.agemo/config/ @@ -92,4 +100,4 @@ COPY --from=build /sdv/.agemo/config/ /sdv/.agemo/config/ EXPOSE 50051 # What the container should run when it is started. -CMD ["/sdv/container_startup.sh"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/Dockerfile.mosquitto b/Dockerfile.mosquitto.amd64 similarity index 98% rename from Dockerfile.mosquitto rename to Dockerfile.mosquitto.amd64 index 3905c3e..199d9a0 100644 --- a/Dockerfile.mosquitto +++ b/Dockerfile.mosquitto.amd64 @@ -16,4 +16,4 @@ WORKDIR /mosquitto/config COPY ./pub-sub-service/src/connectors/mosquitto.conf ./mosquitto.conf -EXPOSE 1883 \ No newline at end of file +EXPOSE 1883 diff --git a/Dockerfile.mosquitto.arm64 b/Dockerfile.mosquitto.arm64 index c55b9e5..4299f0b 100644 --- a/Dockerfile.mosquitto.arm64 +++ b/Dockerfile.mosquitto.arm64 @@ -16,4 +16,5 @@ WORKDIR /mosquitto/config COPY ./pub-sub-service/src/connectors/mosquitto.conf ./mosquitto.conf -EXPOSE 1883 \ No newline at end of file +# Expose the port that the mqtt broker listens on. +EXPOSE 1883 diff --git a/Dockerfile.samples b/Dockerfile.samples.amd64 similarity index 82% rename from Dockerfile.samples rename to Dockerfile.samples.amd64 index c2daa65..23b6749 100644 --- a/Dockerfile.samples +++ b/Dockerfile.samples.amd64 @@ -12,8 +12,11 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 -FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME=simple-publisher +ARG UID=10001 + +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME WORKDIR /sdv COPY ./ . @@ -26,13 +29,12 @@ RUN apt update && apt upgrade -y && apt install -y \ protobuf-compiler # Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} +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 ) -# Build the application with the 'containerize' feature. +# Build the application. RUN cargo build --release -p "${APP_NAME}" # Copy the built application to working directory. @@ -50,10 +52,19 @@ RUN cp ./target/release/"${APP_NAME}" /sdv/service # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM 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 -ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ @@ -79,11 +90,8 @@ ENV AGEMO_SAMPLES_HOME=/sdv/.agemo # Copy the executable from the "build" stage. COPY --from=build /sdv/service /sdv/ -# Copy startup script. -COPY --from=build /sdv/container_startup.sh /sdv/container_startup.sh - # Copy default configs. COPY --from=build /sdv/.agemo-samples/config/ /sdv/.agemo/config/ # What the container should run when it is started. -CMD ["/sdv/container_startup.sh"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/Dockerfile.samples.arm64 b/Dockerfile.samples.arm64 index 3f412f5..2d7544a 100644 --- a/Dockerfile.samples.arm64 +++ b/Dockerfile.samples.arm64 @@ -12,8 +12,11 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 -FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME=simple-publisher +ARG UID=10001 + +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME WORKDIR /sdv COPY ./ . @@ -27,15 +30,14 @@ RUN apt update && apt upgrade -y && apt install -y \ gcc-aarch64-linux-gnu # Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} +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 ) RUN rustup target add aarch64-unknown-linux-gnu -# Build the application with the 'containerize' feature. +# Build the application. RUN cargo build --release --target=aarch64-unknown-linux-gnu -p "${APP_NAME}" # Copy the built application to working directory. @@ -53,10 +55,19 @@ RUN cp ./target/aarch64-unknown-linux-gnu/release/"${APP_NAME}" /sdv/service # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM docker.io/arm64v8/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 -ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ @@ -82,11 +93,8 @@ ENV AGEMO_SAMPLES_HOME=/sdv/.agemo # Copy the executable from the "build" stage. COPY --from=build /sdv/service /sdv/ -# Copy startup script. -COPY --from=build /sdv/container_startup.sh /sdv/container_startup.sh - # Copy default configs. COPY --from=build /sdv/.agemo-samples/config/ /sdv/.agemo/config/ # What the container should run when it is started. -CMD ["/sdv/container_startup.sh"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/container/scripts/argument_sanitizer.sh b/container/scripts/argument_sanitizer.sh new file mode 100755 index 0000000..48ace77 --- /dev/null +++ b/container/scripts/argument_sanitizer.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. +# SPDX-License-Identifier: MIT + +# Exits immediately on failure. +set -e + +# Function to display usage information +usage() { + echo "Usage: $0 [-a|--arg-value] [-r|--regex] " + echo "Example:" + echo " $0 -a \"\${APP_NAME}\" -r \"^[a-zA-Z_0-9-]+$\"" +} + +# Parse command line arguments +while [[ $# -gt 0 ]] +do + key="$1" + + case $key in + -a|--arg-value) + arg_value="$2" + shift # past argument + shift # past value + ;; + -r|--regex) + regex="$2" + shift # past argument + shift # past value + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $key" + usage + exit 1 + esac +done + +# Check if all required arguments have been set +if [[ -z "${arg_value}" || -z "${regex}" ]]; then + echo "Error: Missing required arguments:" + [[ -z "${arg_value}" ]] && echo " -a|--arg-value" + [[ -z "${regex}" ]] && echo " -r|--regex" + echo -e "\n" + usage + exit 1 +fi + +sanitized=$(echo "${arg_value}" | tr -dc "${regex}"); +[ "$sanitized" = "${arg_value}" ] || { + echo "ARG is invalid. ARG='${arg_value}' sanitized='${sanitized}'"; + exit 1 +} + +echo -e "\nARG with value '${arg_value}' is sanitized" +exit 0 diff --git a/container_startup.sh b/container/scripts/container_startup.sh similarity index 88% rename from container_startup.sh rename to container/scripts/container_startup.sh index 73be244..48d508e 100755 --- a/container_startup.sh +++ b/container/scripts/container_startup.sh @@ -8,6 +8,6 @@ set -e # Copy any configuration files present to service configuration. -cp -rn /mnt/config /sdv/.agemo +cp -rf /mnt/config /sdv/.agemo /sdv/service diff --git a/docs/containers.md b/docs/containers.md index 8f7c231..8c5139e 100644 --- a/docs/containers.md +++ b/docs/containers.md @@ -1,12 +1,16 @@ ## Containers -### Dockerfiles +This repository provides several Dockerfiles to enable building of OCI container images. This +document has instructions for building and running the provided Dockerfiles in +[Docker](#docker-containers) and [Podman](#podman-containers). Refer to the +[Dockerfiles](#dockerfiles) section to select the appropriate Dockerfile. -This repository currently provides the following Dockerfiles: +### Dockerfiles #### Pub Sub Service -- [Dockerfile](../Dockerfile) - Dockerfile used to build the `Pub Sub Service`. +- [Dockerfile.amd64](../Dockerfile.amd64) - Dockerfile used to build the `Pub Sub Service` for the +x86-64 architecture. - [Dockerfile.arm64](../Dockerfile.arm64) - Dockerfile used to build the `Pub Sub Service` for the aarch64 architecture. @@ -15,15 +19,15 @@ in the project's root. #### Mosquitto MQTT Broker -- [Dockerfile.mosquitto](../Dockerfile.mosquitto) - Dockerfile used to build the -`Mosquitto MQTT Broker` with the appropriate configuration. +- [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. #### Sample Applications -- [Dockerfile.samples](../Dockerfile.samples) - Dockerfile used to build one of the sample -applications. +- [Dockerfile.samples.amd64](../Dockerfile.samples.amd64) - Dockerfile used to build one of the +sample applications for the x86-64 architecture. - [Dockerfile.samples.arm64](../Dockerfile.samples.arm64) - Dockerfile used to build one of the sample applications for the aarch64 architecture. @@ -50,7 +54,7 @@ Dockerfile: For example, to build an image for the `pub-sub-service` project: ```shell - docker build -t pub_sub_service -f Dockerfile . + docker build -t pub_sub_service -f Dockerfile.amd64 . ``` Or to build an image for the `chariott-publisher` sample for aarch64: @@ -136,7 +140,7 @@ Dockerfile: For example, to build an image for the `pub-sub-service` project: ```shell - podman build -t pub_sub_service -f Dockerfile . + podman build -t pub_sub_service -f Dockerfile.amd64 . ``` Or to build an image for the `chariott-publisher` sample for aarch64: From 272611d0ba2e77c8bf36a63ddc2396af8e59589a Mon Sep 17 00:00:00 2001 From: Devin Kelley <105753233+devkelley@users.noreply.github.com> Date: Thu, 30 Nov 2023 12:25:34 -0800 Subject: [PATCH 3/7] rearranged sanitizer args --- Dockerfile.arm64 | 12 ++++++------ Dockerfile.mosquitto.amd64 | 1 + Dockerfile.samples.amd64 | 12 ++++++------ Dockerfile.samples.arm64 | 12 ++++++------ 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 8843814..b28e72a 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -21,6 +21,12 @@ 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 ) + # Add Build dependencies. RUN apt update && apt upgrade -y && apt install -y \ cmake \ @@ -29,12 +35,6 @@ RUN apt update && apt upgrade -y && apt install -y \ protobuf-compiler \ gcc-aarch64-linux-gnu -# 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 ) - RUN rustup target add aarch64-unknown-linux-gnu # Build the application. diff --git a/Dockerfile.mosquitto.amd64 b/Dockerfile.mosquitto.amd64 index 199d9a0..4eeddea 100644 --- a/Dockerfile.mosquitto.amd64 +++ b/Dockerfile.mosquitto.amd64 @@ -16,4 +16,5 @@ WORKDIR /mosquitto/config COPY ./pub-sub-service/src/connectors/mosquitto.conf ./mosquitto.conf +# Expose the port that the mqtt broker listens on. EXPOSE 1883 diff --git a/Dockerfile.samples.amd64 b/Dockerfile.samples.amd64 index 23b6749..b625b54 100644 --- a/Dockerfile.samples.amd64 +++ b/Dockerfile.samples.amd64 @@ -21,6 +21,12 @@ 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 ) + # Add Build dependencies. RUN apt update && apt upgrade -y && apt install -y \ cmake \ @@ -28,12 +34,6 @@ RUN apt update && apt upgrade -y && apt install -y \ pkg-config \ protobuf-compiler -# 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 ) - # Build the application. RUN cargo build --release -p "${APP_NAME}" diff --git a/Dockerfile.samples.arm64 b/Dockerfile.samples.arm64 index 2d7544a..c2e7637 100644 --- a/Dockerfile.samples.arm64 +++ b/Dockerfile.samples.arm64 @@ -21,6 +21,12 @@ 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 ) + # Add Build dependencies. RUN apt update && apt upgrade -y && apt install -y \ cmake \ @@ -29,12 +35,6 @@ RUN apt update && apt upgrade -y && apt install -y \ protobuf-compiler \ gcc-aarch64-linux-gnu -# 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 ) - RUN rustup target add aarch64-unknown-linux-gnu # Build the application. From ffa04f09edac15ad935cd58bdfc9ac9c0f1e614d Mon Sep 17 00:00:00 2001 From: Devin Kelley <105753233+devkelley@users.noreply.github.com> Date: Fri, 1 Dec 2023 14:35:53 -0800 Subject: [PATCH 4/7] Add -u to scripts --- container/scripts/argument_sanitizer.sh | 2 +- container/scripts/container_startup.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/container/scripts/argument_sanitizer.sh b/container/scripts/argument_sanitizer.sh index 48ace77..d6ed4da 100755 --- a/container/scripts/argument_sanitizer.sh +++ b/container/scripts/argument_sanitizer.sh @@ -5,7 +5,7 @@ # SPDX-License-Identifier: MIT # Exits immediately on failure. -set -e +set -eu # Function to display usage information usage() { diff --git a/container/scripts/container_startup.sh b/container/scripts/container_startup.sh index 48d508e..0005e4d 100755 --- a/container/scripts/container_startup.sh +++ b/container/scripts/container_startup.sh @@ -5,7 +5,7 @@ # SPDX-License-Identifier: MIT # Exits immediately on failure. -set -e +set -eu # Copy any configuration files present to service configuration. cp -rf /mnt/config /sdv/.agemo From b36a32cfb762667b3c9fe797151335482b76d193 Mon Sep 17 00:00:00 2001 From: Devin Kelley <105753233+devkelley@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:43:31 -0800 Subject: [PATCH 5/7] Add comment to cp command --- container/scripts/container_startup.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/container/scripts/container_startup.sh b/container/scripts/container_startup.sh index 0005e4d..03cfaa4 100755 --- a/container/scripts/container_startup.sh +++ b/container/scripts/container_startup.sh @@ -7,7 +7,9 @@ # Exits immediately on failure. set -eu -# Copy any configuration files present to service configuration. +# Copy any mounted configuration files present to service configuration at runtime. +# If there is a configuration file with the same name at `/sdv/.agemo/config` this will overwrite +# the file with the mounted configuration file. cp -rf /mnt/config /sdv/.agemo /sdv/service From a4def3924a7a4d57ea7477a8c0138f39e157b887 Mon Sep 17 00:00:00 2001 From: Devin Kelley <105753233+devkelley@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:44:11 -0800 Subject: [PATCH 6/7] reword --- container/scripts/container_startup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/scripts/container_startup.sh b/container/scripts/container_startup.sh index 03cfaa4..517f3e9 100755 --- a/container/scripts/container_startup.sh +++ b/container/scripts/container_startup.sh @@ -9,7 +9,7 @@ set -eu # Copy any mounted configuration files present to service configuration at runtime. # If there is a configuration file with the same name at `/sdv/.agemo/config` this will overwrite -# the file with the mounted configuration file. +# that file with the mounted configuration file. cp -rf /mnt/config /sdv/.agemo /sdv/service From 2f4d9e5a2e10ca5183081c1210a321a05b38d56c Mon Sep 17 00:00:00 2001 From: Devin Kelley <105753233+devkelley@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:49:17 -0800 Subject: [PATCH 7/7] fix whitespace --- container/scripts/container_startup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/scripts/container_startup.sh b/container/scripts/container_startup.sh index 517f3e9..e3abc43 100755 --- a/container/scripts/container_startup.sh +++ b/container/scripts/container_startup.sh @@ -9,7 +9,7 @@ set -eu # Copy any mounted configuration files present to service configuration at runtime. # If there is a configuration file with the same name at `/sdv/.agemo/config` this will overwrite -# that file with the mounted configuration file. +# that file with the mounted configuration file. cp -rf /mnt/config /sdv/.agemo /sdv/service