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/Update Dockerfiles for arm64 support and documentation #23

Merged
merged 7 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
3 changes: 3 additions & 0 deletions .cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lgcc" ]
3 changes: 1 addition & 2 deletions .github/workflows/dotnet-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
- main

env:
DOTNET_VERSION: 6.0.119
DOTNET_VERSION: 6.0.x

jobs:
static_code_analysis:
Expand All @@ -21,7 +21,6 @@ jobs:
uses: actions/setup-dotnet@v3
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
global-json-file: cloud_connectors/azure/digital_twins_connector/global.json
- name: Cache NuGet dependencies
uses: actions/cache@v3
with:
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/security-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install .NET 6.0.119
- name: Install .NET 6.0.x
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.119
global-json-file: cloud_connectors/azure/digital_twins_connector/global.json
dotnet-version: '6.0.x'
- name: Cache NuGet dependencies
uses: actions/cache@v3
with:
Expand Down
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 32 additions & 12 deletions Dockerfile.freyja_apps → Dockerfile.freyja_apps.amd64
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,30 @@
# 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=freyja-in-memory-app
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 \
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}" --features containerize
# Build the application.
RUN cargo build --release -p "${APP_NAME}"

# Copy the built application to working directory.
RUN cp ./target/release/"${APP_NAME}" /sdv/service
Expand All @@ -47,10 +50,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 "" \
Expand All @@ -59,6 +71,14 @@ RUN adduser \
--no-create-home \
--uid "${UID}" \
appuser

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

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

USER appuser

WORKDIR /sdv
Expand All @@ -70,4 +90,4 @@ COPY --from=build /sdv/target/release/build/ /sdv/target/release/build/
ENV FREYJA_HOME=/sdv/.freyja

# What the container should run when it is started.
CMD ["/sdv/service"]
CMD ["/sdv/scripts/container_startup.sh"]
96 changes: 96 additions & 0 deletions Dockerfile.freyja_apps.arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
# SPDX-License-Identifier: MIT

# 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
ARG APP_NAME=freyja-in-memory-app
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 \
libssl-dev \
pkg-config \
protobuf-compiler \
gcc-aarch64-linux-gnu

RUN rustup target add aarch64-unknown-linux-gnu

# Build the application.
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
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/.freyja/config
RUN chown appuser /sdv/.freyja/config

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

USER appuser

WORKDIR /sdv

# Copy the executable from the "build" stage.
COPY --from=build /sdv/service /sdv/
COPY --from=build /sdv/target/aarch64-unknown-linux-gnu/release/build/ /sdv/target/aarch64-unknown-linux-gnu/release/build/

ENV FREYJA_HOME=/sdv/.freyja

# What the container should run when it is started.
CMD ["/sdv/scripts/container_startup.sh"]
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ The Freyja examples include:
- [Example Freyja Apps](./freyja_apps/): These are examples of how to write a Freyja application using its plugin model. Each example has a README describing its usage, and the `template` app can be used to get started with your own adapters.
- [Example Freyja Adapters](./freyja_adapters/): These are examples of adapters that can be used with Freyja. Each adapter has a README describing its usage.
- [Example Cloud Connectors](./cloud_connectors/): These are examples of cloud connectors that Freyja can interface with through the `CloudAdapter` trait. These serve as examples of how to integrate with specific cloud solutions.

### Supported Ibeji Samples

This repository provides freyja configuration overrides in the [`.freyja`](.freyja/) directory that support the following Ibeji samples:

- [managed subscribe](https://github.com/eclipse-ibeji/ibeji/tree/main/samples/managed_subscribe)
- [mixed](https://github.com/eclipse-ibeji/ibeji/tree/main/samples/mixed)
- [property](https://github.com/eclipse-ibeji/ibeji/tree/main/samples/property)
27 changes: 27 additions & 0 deletions cloud_connectors/azure/Dockerfile.dt_connector.amd64
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /App

# Copy everything
COPY ./ .
WORKDIR /App/digital_twins_connector/src/core/
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
RUN cp -rn ./out /App/out

# Build runtime image
FROM docker.io/library/ubuntu:22.04 AS final

# Install dotnet and az cli
RUN apt update -y && apt install -y dotnet-sdk-6.0 curl
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash

WORKDIR /sdv

COPY --from=build-env /App/out .
COPY --from=build-env /App/container/scripts/container_startup.sh /sdv/scripts/container_startup.sh

ENV ASPNETCORE_URLS "http://0.0.0.0:5176"

CMD ["/sdv/scripts/container_startup.sh"]
27 changes: 27 additions & 0 deletions cloud_connectors/azure/Dockerfile.dt_connector.arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /App

# Copy everything
COPY ./ .
WORKDIR /App/digital_twins_connector/src/core/
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
RUN cp -rn ./out /App/out

# Build runtime image
FROM docker.io/arm64v8/ubuntu:22.04 AS final

# Install dotnet and az cli
RUN apt update -y && apt install -y dotnet-sdk-6.0 curl
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash

WORKDIR /sdv

COPY --from=build-env /App/out .
COPY --from=build-env /App/container/scripts/container_startup.sh /sdv/scripts/container_startup.sh

ENV ASPNETCORE_URLS "http://0.0.0.0:5176"

CMD ["/sdv/scripts/container_startup.sh"]
22 changes: 22 additions & 0 deletions cloud_connectors/azure/container/scripts/container_startup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
# SPDX-License-Identifier: MIT

# Exits immediately on failure.
set -eu

# Copy any configuration files present to service configuration.
cp -rf /mnt/config /sdv/

# Acquire access token scoped to the Azure Digital Twin Service.
az login --use-device-code --scope https://digitaltwins.azure.net/.default

# Set azure subscription only if SUBSCRIPTION_ID is set.
if [ -n "$SUBSCRIPTION_ID" ]; then
az account set --subscription "$SUBSCRIPTION_ID"
fi

# Start the Digital Twin Connector service.
dotnet ./DigitalTwinsConnector.dll
9 changes: 9 additions & 0 deletions cloud_connectors/azure/digital_twins_connector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,12 @@ The first gRPC client call to the Digital Twins Connector's gRPC server could be
```shell
dotnet run --project src/core/
```

## Containerize the Azure Digital Twins Cloud Connector Application

To build and run the application in a container, follow the steps under
[Docker Containers](../../../container/README.md#docker-containers) or
[Podman Containers](../../../container/README.md#podman-containers).

Set `CONFIG_HOME` to point to the directory containing the `adt_instance_config.json` file modified
in step 4 of [Manual Azure Digital Twins Setup](#manual-azure-digital-twins-setup).
5 changes: 0 additions & 5 deletions cloud_connectors/azure/digital_twins_connector/global.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license.
// SPDX-License-Identifier: MIT

using System.Reflection;
using System.Text.Json;

using Azure.DigitalTwins.Core;
Expand All @@ -11,17 +12,17 @@

namespace Microsoft.ESDV.CloudConnector.Azure
{
class AzureDigitalTwinsInstanceConfig

Check failure on line 15 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / security_audit_csharp (csharp)

Type 'AzureDigitalTwinsInstanceConfig' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 15 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / security_audit_csharp (csharp)

Type 'AzureDigitalTwinsInstanceConfig' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 15 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / static_code_analysis

Type 'AzureDigitalTwinsInstanceConfig' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 15 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / static_code_analysis

Type 'AzureDigitalTwinsInstanceConfig' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
public string AzureDigitalTwinsInstanceUrl { get; set; }
}

class Program

Check failure on line 20 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / security_audit_csharp (csharp)

Type 'Program' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 20 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / security_audit_csharp (csharp)

Type 'Program' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 20 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / static_code_analysis

Type 'Program' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 20 in cloud_connectors/azure/digital_twins_connector/src/core/Program.cs

View workflow job for this annotation

GitHub Actions / static_code_analysis

Type 'Program' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
static void Main(string[] args)
{
const string AZURE_DIGITAL_TWINS_INSTANCE_CONFIG_PATH = @"bin/Debug/net6.0/config/adt_instance_config.json";
string contents = File.ReadAllText(AZURE_DIGITAL_TWINS_INSTANCE_CONFIG_PATH);
string azure_digital_twins_config_path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"config/adt_instance_config.json");
string contents = File.ReadAllText(azure_digital_twins_config_path);
AzureDigitalTwinsInstanceConfig adtInstanceConfig = JsonSerializer.Deserialize<AzureDigitalTwinsInstanceConfig>(contents);

// Configure the builder
Expand Down
Loading
Loading