diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 472329c..e99880f 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -1,6 +1,12 @@ name: GitHub -on: [push, pull_request] +on: + push: + branches: + - main + pull_request: + branches: + - main jobs: diff --git a/.github/workflows/gitlab.yml b/.github/workflows/gitlab.yml index f2bb271..47a666e 100644 --- a/.github/workflows/gitlab.yml +++ b/.github/workflows/gitlab.yml @@ -1,6 +1,12 @@ name: GitLab -on: [push, pull_request] +on: + push: + branches: + - main + pull_request: + branches: + - main jobs: @@ -11,7 +17,7 @@ jobs: run: | curl --silent --fail --request POST --form "token=${{ secrets.DOCKER_ROS_CI_TRIGGER_GITLAB_TOKEN }}" --form "ref=main" --form "variables[DOCKER_ROS_GIT_REF]=${{ github.sha }}" "https://gitlab.ika.rwth-aachen.de/api/v4/projects/1886/trigger/pipeline" | jq -r .id > id - name: Upload pipeline ID - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: id_ros path: id @@ -21,7 +27,7 @@ jobs: needs: trigger-ros steps: - name: Get pipeline ID - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: id_ros - name: Wait for pipeline completion @@ -47,7 +53,7 @@ jobs: run: | curl --silent --fail --request POST --form "token=${{ secrets.DOCKER_ROS_CI_TRIGGER_GITLAB_TOKEN }}" --form "ref=ros2" --form "variables[DOCKER_ROS_GIT_REF]=${{ github.sha }}" "https://gitlab.ika.rwth-aachen.de/api/v4/projects/1886/trigger/pipeline" | jq -r .id > id - name: Upload pipeline ID - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: id_ros2 path: id @@ -57,7 +63,7 @@ jobs: needs: trigger-ros2 steps: - name: Get pipeline ID - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: id_ros2 - name: Wait for pipeline completion diff --git a/.gitlab-ci/docker-ros.yml b/.gitlab-ci/docker-ros.yml index 5b79abf..19e2fd6 100644 --- a/.gitlab-ci/docker-ros.yml +++ b/.gitlab-ci/docker-ros.yml @@ -21,6 +21,7 @@ variables: CUSTOM_SCRIPT_FILE: docker/custom.sh # Relative filepath to script containing custom installation commands DEV_IMAGE_NAME: ${IMAGE_NAME} # Image name of dev image DEV_IMAGE_TAG: ${IMAGE_TAG}-dev # Image tag of dev image + DISABLE_ROS_INSTALLATION: 'false' # Disable automatic installation of `ros-$ROS_DISTRO-ros-core` package, e.g., if ROS is already installed in `base-image` and package is not available for the OS ENABLE_CONTINUE_BUILD_DESPITE_ERRORS: 'false' # Enable `catkin build --continue-on-failure` / `colcon build --continue-on-error` ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS: 'false' # Enable `rosdep install -r` ENABLE_INDUSTRIAL_CI: 'false' # Enable industrial_ci @@ -32,6 +33,7 @@ variables: ENABLE_RECURSIVE_VCS_IMPORT: 'true' # Enable recursive discovery of files named `*.repos` ENABLE_ROS1_DEVEL_SPACE: 'false' # Enable building to ROS devel space instead of install space (ROS 1 only) ENABLE_SINGLEARCH_PUSH: 'false' # Enable push of single arch images with [-amd64|-arm64] postfix + ENABLE_SLIM: 'true' # Enable an extra slimmed run image via slim (only if run stage is targeted) GIT_HTTPS_PASSWORD: ${CI_JOB_TOKEN} # Password for cloning private Git repositories via HTTPS GIT_HTTPS_SERVER: ${CI_SERVER_HOST} # Server URL (without protocol) for cloning private Git repositories via HTTPS GIT_HTTPS_USER: gitlab-ci-token # Username for cloning private Git repositories via HTTPS @@ -45,6 +47,9 @@ variables: REGISTRY: ${CI_REGISTRY} # Docker registry to push images to RMW_IMPLEMENTATION: 'rmw_cyclonedds_cpp' # RMW implementation to use (only for ROS 2) ROS_DISTRO: '' # ROS Distro (required if ROS is not installed in `base-image`) + SLIM_BUILD_ARGS: '--sensor-ipc-mode proxy --continue-after=10 --show-clogs --http-probe=false' # Arguments to `slim build` (except for `--target` and `--tag`) + SLIM_IMAGE_NAME: ${IMAGE_NAME} # Image name of slim run image + SLIM_IMAGE_TAG: ${IMAGE_TAG}-slim # Image tag of slim run image TARGET: run # Target stage of Dockerfile (comma-separated list) [dev|build|run] VCS_IMPORT_FILE: .repos # Relative filepath to file containing additional repos to install via vcstools (only relevant if ENABLE_RECURSIVE_VCS_IMPORT=false) # ----- @@ -53,25 +58,32 @@ variables: _RUN_IMAGE: ${IMAGE_NAME}:${IMAGE_TAG} _BUILD_IMAGE: ${BUILD_IMAGE_NAME}:${BUILD_IMAGE_TAG} _DEV_IMAGE: ${DEV_IMAGE_NAME}:${DEV_IMAGE_TAG} + _SLIM_IMAGE: ${SLIM_IMAGE_NAME}:${SLIM_IMAGE_TAG} - _IMAGE_DEV_CI: ${_DEV_IMAGE}_${CI_COMMIT_REF_SLUG}_ci + _IMAGE_BUILD_CI_AMD64: ${_IMAGE_BUILD_CI}-amd64 + _IMAGE_BUILD_CI_ARM64: ${_IMAGE_BUILD_CI}-arm64 _IMAGE_BUILD_CI: ${_BUILD_IMAGE}_${CI_COMMIT_REF_SLUG}_ci - _IMAGE_RUN_CI: ${_RUN_IMAGE}_${CI_COMMIT_REF_SLUG}_ci + _IMAGE_BUILD_LATEST: ${BUILD_IMAGE_NAME}:latest-build + _IMAGE_BUILD_TAG: ${BUILD_IMAGE_NAME}:${CI_COMMIT_TAG}-build + _IMAGE_BUILD_TARGET_TAG: ${_BUILD_IMAGE}-${CI_COMMIT_TAG} _IMAGE_DEV_CI_AMD64: ${_IMAGE_DEV_CI}-amd64 _IMAGE_DEV_CI_ARM64: ${_IMAGE_DEV_CI}-arm64 - _IMAGE_BUILD_CI_AMD64: ${_IMAGE_BUILD_CI}-amd64 - _IMAGE_BUILD_CI_ARM64: ${_IMAGE_BUILD_CI}-arm64 + _IMAGE_DEV_CI: ${_DEV_IMAGE}_${CI_COMMIT_REF_SLUG}_ci + _IMAGE_DEV_LATEST: ${DEV_IMAGE_NAME}:latest-dev + _IMAGE_DEV_TAG: ${DEV_IMAGE_NAME}:${CI_COMMIT_TAG}-dev + _IMAGE_DEV_TARGET_TAG: ${_DEV_IMAGE}-${CI_COMMIT_TAG} _IMAGE_RUN_CI_AMD64: ${_IMAGE_RUN_CI}-amd64 _IMAGE_RUN_CI_ARM64: ${_IMAGE_RUN_CI}-arm64 - _IMAGE_DEV_LATEST: ${DEV_IMAGE_NAME}:latest-dev - _IMAGE_BUILD_LATEST: ${BUILD_IMAGE_NAME}:latest-build + _IMAGE_RUN_CI: ${_RUN_IMAGE}_${CI_COMMIT_REF_SLUG}_ci _IMAGE_RUN_LATEST: ${IMAGE_NAME}:latest - _IMAGE_DEV_TARGET_TAG: ${_DEV_IMAGE}-${CI_COMMIT_TAG} - _IMAGE_BUILD_TARGET_TAG: ${_BUILD_IMAGE}-${CI_COMMIT_TAG} - _IMAGE_RUN_TARGET_TAG: ${_RUN_IMAGE}-${CI_COMMIT_TAG} - _IMAGE_DEV_TAG: ${DEV_IMAGE_NAME}:${CI_COMMIT_TAG}-dev - _IMAGE_BUILD_TAG: ${BUILD_IMAGE_NAME}:${CI_COMMIT_TAG}-build _IMAGE_RUN_TAG: ${IMAGE_NAME}:${CI_COMMIT_TAG} + _IMAGE_RUN_TARGET_TAG: ${_RUN_IMAGE}-${CI_COMMIT_TAG} + _IMAGE_SLIM_CI_AMD64: ${_IMAGE_SLIM_CI}-amd64 + _IMAGE_SLIM_CI_ARM64: ${_IMAGE_SLIM_CI}-arm64 + _IMAGE_SLIM_CI: ${_SLIM_IMAGE}_${CI_COMMIT_REF_SLUG}_ci + _IMAGE_SLIM_LATEST: ${SLIM_IMAGE_NAME}:latest-slim + _IMAGE_SLIM_TAG: ${SLIM_IMAGE_NAME}:${CI_COMMIT_TAG}-slim + _IMAGE_SLIM_TARGET_TAG: ${_SLIM_IMAGE}-${CI_COMMIT_TAG} GIT_SUBMODULE_STRATEGY: recursive DOCKER_DRIVER: overlay2 @@ -84,6 +96,7 @@ stages: - Build build Images - Build run Images - Test ROS Industrial CI + - Slim Images - Push Multi-Arch Images @@ -96,7 +109,7 @@ default: - amd64 before_script: - echo -e "section_start:`date +%s`:setup_section[collapsed=true]\r\e[0K[docker-ros] Setup docker-ros" - - apk add bash + - apk add --update bash - cd ${BUILD_CONTEXT} - |- if [[ ! -d docker/docker-ros ]]; then @@ -133,6 +146,7 @@ dev-amd64: _TARGET: dev IMAGE: ${_IMAGE_DEV_CI_AMD64} ENABLE_SINGLEARCH_PUSH: 'true' + ENABLE_SLIM: 'false' _IMAGE_POSTFIX: _${CI_COMMIT_REF_SLUG}_ci dev-arm64: @@ -146,6 +160,7 @@ dev-arm64: _TARGET: dev IMAGE: ${_IMAGE_DEV_CI_ARM64} ENABLE_SINGLEARCH_PUSH: 'true' + ENABLE_SLIM: 'false' _IMAGE_POSTFIX: _${CI_COMMIT_REF_SLUG}_ci build-amd64: @@ -194,6 +209,7 @@ run-amd64: _TARGET: run IMAGE: ${_IMAGE_RUN_CI_AMD64} ENABLE_SINGLEARCH_PUSH: 'true' + ENABLE_SLIM: 'false' _IMAGE_POSTFIX: _${CI_COMMIT_REF_SLUG}_ci run-arm64: @@ -212,10 +228,12 @@ run-arm64: _TARGET: run IMAGE: ${_IMAGE_RUN_CI_ARM64} ENABLE_SINGLEARCH_PUSH: 'true' + ENABLE_SLIM: 'false' _IMAGE_POSTFIX: _${CI_COMMIT_REF_SLUG}_ci .test: + stage: Test ROS Industrial CI variables: UPSTREAM_WORKSPACE: ${BUILD_CONTEXT}/.repos TARGET_WORKSPACE: ${BUILD_CONTEXT} @@ -231,10 +249,13 @@ run-arm64: fi - git clone --branch master --depth 1 https://github.com/ros-industrial/industrial_ci.git .industrial_ci - test -f ${BUILD_CONTEXT}/.repos || echo "repositories:" > ${BUILD_CONTEXT}/.repos + - |- + if [ "$RMW_IMPLEMENTATION" = "rmw_zenoh_cpp" ]; then + export UNDERLAY="/opt/ws_rmw_zenoh/install" + fi script: .industrial_ci/gitlab.sh Test dev-amd64: - stage: Test ROS Industrial CI extends: .test needs: - job: dev-amd64 @@ -245,7 +266,6 @@ Test dev-amd64: _PLATFORM: amd64 Test dev-arm64: - stage: Test ROS Industrial CI extends: .test tags: [privileged, arm64] needs: @@ -257,7 +277,6 @@ Test dev-arm64: _PLATFORM: arm64 Test run-amd64: - stage: Test ROS Industrial CI extends: .test needs: - job: run-amd64 @@ -268,7 +287,6 @@ Test run-amd64: _PLATFORM: amd64 Test run-arm64: - stage: Test ROS Industrial CI extends: .test needs: - job: run-arm64 @@ -279,6 +297,51 @@ Test run-arm64: _PLATFORM: arm64 +.slim: + stage: Slim Images + before_script: + - apk add --update --upgrade curl tar + - curl -L -o ds.tar.gz ${SLIM_DOWNLOAD_URL} + - tar -xvf ds.tar.gz + - cd dist_linux* + - docker login -u ${REGISTRY_USER} -p ${REGISTRY_PASSWORD} ${REGISTRY} + - docker pull ${FAT_IMAGE} + script: + - ./slim build --target ${FAT_IMAGE} --tag ${SLIM_IMAGE} ${SLIM_BUILD_ARGS} + - docker push ${SLIM_IMAGE} + +Slim run-amd64: + stage: Slim Images + extends: .slim + needs: + - job: run-amd64 + optional: true + - job: Test run-amd64 + optional: true + rules: + - if: $ENABLE_SLIM == 'true' && $PLATFORM =~ /.*amd64.*/ && $TARGET =~ /.*run.*/ + variables: + FAT_IMAGE: ${_IMAGE_RUN_CI_AMD64} + SLIM_IMAGE: ${_IMAGE_SLIM_CI_AMD64} + SLIM_DOWNLOAD_URL: "https://github.com/slimtoolkit/slim/releases/download/1.40.11/dist_linux.tar.gz" + +Slim run-arm64: + stage: Slim Images + extends: .slim + tags: [privileged, arm64] + needs: + - job: run-arm64 + optional: true + - job: Test run-arm64 + optional: true + rules: + - if: $ENABLE_SLIM == 'true' && $PLATFORM =~ /.*arm64.*/ && $TARGET =~ /.*run.*/ + variables: + FAT_IMAGE: ${_IMAGE_RUN_CI_ARM64} + SLIM_IMAGE: ${_IMAGE_SLIM_CI_ARM64} + SLIM_DOWNLOAD_URL: "https://github.com/slimtoolkit/slim/releases/download/1.40.11/dist_linux_arm64.tar.gz" + + .push: needs: - job: dev-amd64 @@ -301,6 +364,10 @@ Test run-arm64: optional: true - job: Test run-arm64 optional: true + - job: Slim run-amd64 + optional: true + - job: Slim run-arm64 + optional: true rules: - if: $PLATFORM == '' || $TARGET == '' when: never @@ -319,6 +386,10 @@ Test run-arm64: docker manifest create ${IMG_RUN} --amend ${_IMAGE_RUN_CI_AMD64} --amend ${_IMAGE_RUN_CI_ARM64} docker manifest push ${IMG_RUN} fi + if [[ "${ENABLE_SLIM}" == 'true' && "${TARGET}" =~ run ]]; then + docker manifest create ${IMG_SLIM} --amend ${_IMAGE_SLIM_CI_AMD64} --amend ${_IMAGE_SLIM_CI_ARM64} + docker manifest push ${IMG_SLIM} + fi elif [[ "${PLATFORM}" =~ amd64 ]]; then if [[ "${TARGET}" =~ dev ]]; then docker pull ${_IMAGE_DEV_CI_AMD64} @@ -335,6 +406,11 @@ Test run-arm64: docker tag ${_IMAGE_RUN_CI_AMD64} ${IMG_RUN} docker push ${IMG_RUN} fi + if [[ "${ENABLE_SLIM}" == 'true' && "${TARGET}" =~ run ]]; then + docker pull ${_IMAGE_SLIM_CI_AMD64} + docker tag ${_IMAGE_SLIM_CI_AMD64} ${IMG_SLIM} + docker push ${IMG_SLIM} + fi elif [[ "${PLATFORM}" =~ arm64 ]]; then if [[ "${TARGET}" =~ dev ]]; then docker pull ${_IMAGE_DEV_CI_ARM64} @@ -351,6 +427,11 @@ Test run-arm64: docker tag ${_IMAGE_RUN_CI_ARM64} ${IMG_RUN} docker push ${IMG_RUN} fi + if [[ "${ENABLE_SLIM}" == 'true' && "${TARGET}" =~ run ]]; then + docker pull ${_IMAGE_SLIM_CI_ARM64} + docker tag ${_IMAGE_SLIM_CI_ARM64} ${IMG_SLIM} + docker push ${IMG_SLIM} + fi fi Push CI: @@ -365,6 +446,7 @@ Push CI: IMG_DEV: ${_IMAGE_DEV_CI} IMG_BUILD: ${_IMAGE_BUILD_CI} IMG_RUN: ${_IMAGE_RUN_CI} + IMG_SLIM: ${_IMAGE_SLIM_CI} Push: stage: Push Multi-Arch Images @@ -376,6 +458,7 @@ Push: IMG_DEV: ${_DEV_IMAGE} IMG_BUILD: ${_BUILD_IMAGE} IMG_RUN: ${_RUN_IMAGE} + IMG_SLIM: ${_SLIM_IMAGE} Push latest: stage: Push Multi-Arch Images @@ -387,6 +470,7 @@ Push latest: IMG_DEV: ${_IMAGE_DEV_LATEST} IMG_BUILD: ${_IMAGE_BUILD_LATEST} IMG_RUN: ${_IMAGE_RUN_LATEST} + IMG_SLIM: ${_IMAGE_SLIM_LATEST} Push target tag: stage: Push Multi-Arch Images @@ -398,6 +482,7 @@ Push target tag: IMG_DEV: ${_IMAGE_DEV_TARGET_TAG} IMG_BUILD: ${_IMAGE_BUILD_TARGET_TAG} IMG_RUN: ${_IMAGE_RUN_TARGET_TAG} + IMG_SLIM: ${_IMAGE_SLIM_TARGET_TAG} Push tag: stage: Push Multi-Arch Images @@ -409,3 +494,4 @@ Push tag: IMG_DEV: ${_IMAGE_DEV_TAG} IMG_BUILD: ${_IMAGE_BUILD_TAG} IMG_RUN: ${_IMAGE_RUN_TAG} + IMG_SLIM: ${_IMAGE_SLIM_TAG} diff --git a/CITATION.cff b/CITATION.cff index 97a4c19..3070c60 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -13,12 +13,13 @@ authors: preferred-citation: title: "Enabling the Deployment of Any-Scale Robotic Applications in Microservice-Based Service-Oriented Architectures through Automated Containerization" - type: misc - # conference: - # name: - # month: - year: 2023 - # doi: "" + type: conference-paper + conference: + name: "2024 IEEE International Conference on Robotics and Automation (ICRA)" + year: 2024 + pages: "17650-17656" + doi: "10.1109/ICRA57147.2024.10611586" + url: "https://ieeexplore.ieee.org/document/10611586" authors: - given-names: Jean-Pierre family-names: Busch diff --git a/LICENSE b/LICENSE index 33d1c83..b579e18 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Institute for Automotive Engineering (ika), RWTH Aachen University +Copyright (c) 2023-2024 Institute for Automotive Engineering (ika), RWTH Aachen University Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 59dfc01..2eb2af7 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ + +

*docker-ros* automatically builds minimal container images of ROS applications. @@ -16,7 +18,7 @@ > [!IMPORTANT] > This repository is open-sourced and maintained by the [**Institute for Automotive Engineering (ika) at RWTH Aachen University**](https://www.ika.rwth-aachen.de/). > **DevOps, Containerization and Orchestration of Software-Defined Vehicles** are some of many research topics within our [*Vehicle Intelligence & Automated Driving*](https://www.ika.rwth-aachen.de/en/competences/fields-of-research/vehicle-intelligence-automated-driving.html) domain. -> If you would like to learn more about how we can support your DevOps or automated driving efforts, feel free to reach out to us! +> If you would like to learn more about how we can support your advanced driver assistance and automated driving efforts, feel free to reach out to us! > :email: ***opensource@ika.rwth-aachen.de*** - [About](#about) @@ -35,6 +37,9 @@ - [Extra System Dependencies (*pip*)](#extra-system-dependencies-pip) - [Custom Installation Script](#custom-installation-script) - [Extra Image Files](#extra-image-files) +- [Additional Information](#additional-information) + - [User Setup](#user-setup) + - [Slim Deployment Image](#slim-deployment-image) - [Configuration Variables](#configuration-variables) We recommend to use *docker-ros* in combination with our other tools for Docker and ROS. @@ -44,7 +49,7 @@ We recommend to use *docker-ros* in combination with our other tools for Docker ## About -*docker-ros* provides a generic [Dockerfile](docker/Dockerfile) that can be used to build development and deployment Docker images for arbitrary ROS packages or package stacks. Building such images can easily be automated by integrating *docker-ros* into CI through the provided [GitHub action](action.yml) or [GitLab CI template](.gitlab-ci/docker-ros.yml). The development image built by *docker-ros* contains all required dependencies and the source code of your ROS-based repository. The deployment image only contains dependencies and the compiled binaries created by building the ROS packages in the repository. *docker-ros* is also able to build multi-arch Docker images for *amd64* and *arm64* architectures. +*docker-ros* provides a generic [Dockerfile](docker/Dockerfile) that can be used to build development and deployment Docker images for arbitrary ROS packages or package stacks. Building such images can easily be automated by integrating *docker-ros* into CI through the provided [GitHub action](action.yml) or [GitLab CI template](.gitlab-ci/docker-ros.yml). The development image built by *docker-ros* contains all required dependencies and the source code of your ROS-based repository. The deployment image only contains dependencies and the compiled binaries created by building the ROS packages in the repository. *docker-ros* is also able to build multi-arch Docker images for *amd64* and *arm64* architectures. In addition, [*slim*](https://github.com/slimtoolkit/slim) is integrated for slimming Docker image size of the deployment image by up to 30x (see [*Slim Deployment Image*](#slim-deployment-image)). The Dockerfile performs the following steps to build these images: 1. All dependency repositories that are defined in a `.repos` file anywhere in the repository are cloned using [*vcstool*](https://github.com/dirk-thomas/vcstool). @@ -71,7 +76,7 @@ Note that GitHub is currently only offering Linux runners based on the *amd64* a
GitLab -> **Note** +> [!NOTE] > - GitLab runners must be based on the Docker executor, [see here](https://docs.gitlab.com/runner/executors/docker.html) > - GitLab runners must run in privileged mode for Docker-in-Docker, [see here](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode) > - GitLab runners must be tagged with tags `privileged` and either `amd64` or `arm64` depending on their architecture @@ -109,7 +114,7 @@ jobs: docker-ros: runs-on: ubuntu-latest steps: - - uses: ika-rwth-aachen/docker-ros@v1.3.1 + - uses: ika-rwth-aachen/docker-ros@v1.6.1 with: base-image: rwthika/ros2:humble command: ros2 run my_pkg my_node @@ -121,7 +126,7 @@ jobs: ```yml include: - - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.3.1/.gitlab-ci/docker-ros.yml + - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.6.1/.gitlab-ci/docker-ros.yml variables: BASE_IMAGE: rwthika/ros2:humble @@ -140,7 +145,7 @@ jobs: docker-ros: runs-on: ubuntu-latest steps: - - uses: ika-rwth-aachen/docker-ros@v1.3.1 + - uses: ika-rwth-aachen/docker-ros@v1.6.1 with: base-image: rwthika/ros2:humble command: ros2 run my_pkg my_node @@ -153,7 +158,7 @@ jobs: ```yml include: - - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.3.1/.gitlab-ci/docker-ros.yml + - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.6.1/.gitlab-ci/docker-ros.yml variables: BASE_IMAGE: rwthika/ros2:humble @@ -173,7 +178,7 @@ jobs: docker-ros: runs-on: ubuntu-latest steps: - - uses: ika-rwth-aachen/docker-ros@v1.3.1 + - uses: ika-rwth-aachen/docker-ros@v1.6.1 with: base-image: rwthika/ros2:humble command: ros2 run my_pkg my_node @@ -187,7 +192,7 @@ jobs: ```yml include: - - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.3.1/.gitlab-ci/docker-ros.yml + - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.6.1/.gitlab-ci/docker-ros.yml variables: BASE_IMAGE: rwthika/ros2:humble @@ -208,7 +213,7 @@ jobs: docker-ros: runs-on: ubuntu-latest steps: - - uses: ika-rwth-aachen/docker-ros@v1.3.1 + - uses: ika-rwth-aachen/docker-ros@v1.6.1 with: base-image: rwthika/ros2:humble command: ros2 run my_pkg my_node @@ -221,7 +226,7 @@ jobs: ```yml include: - - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.3.1/.gitlab-ci/docker-ros.yml + - remote: https://raw.githubusercontent.com/ika-rwth-aachen/docker-ros/v1.6.1/.gitlab-ci/docker-ros.yml variables: BASE_IMAGE: rwthika/ros2:humble @@ -245,7 +250,7 @@ jobs: platform: [amd64, arm64] runs-on: [self-hosted, "${{ matrix.platform }}"] steps: - - uses: ika-rwth-aachen/docker-ros@v1.3.1 + - uses: ika-rwth-aachen/docker-ros@v1.6.1 with: base-image: rwthika/ros2:humble command: ros2 run my_pkg my_node @@ -283,7 +288,7 @@ jobs: IMAGE="my-image:latest" \ ./docker/docker-ros/scripts/build.sh ``` - > **Note** + > [!NOTE] > You can alternatively store your environment variable configuration in a `.env` file: > ```bash > # .env @@ -334,9 +339,26 @@ If you need to have additional files present in the deployment image, you can us Create a folder `additional-files` in your `docker` folder (or configure a different `ADDITIONAL_FILES_DIR`) and place any files or directories in it. The contents will be copied to `/docker-ros/additional-files` in the image. +## Additional Information + +### User Setup + +Containers of the provided images start with `root` user by default. If the two environment variables `DOCKER_UID` and `DOCKER_GID` are passed, a new user with the corresponding UID/GID is created on the fly. Most importantly, this features allows to mount and edit files of the host user in the container without having to deal with permission issues. + +```bash +docker run --rm -it -e DOCKER_UID=$(id -u) -e DOCKER_GID=$(id -g) -e DOCKER_USER=$(id -un) rwthika/ros:latest +``` + +The password of the custom user is set to its username (`dockeruser:dockeruser` by default). + +### Slim Deployment Image + +*docker-ros* integrates the [*slim*](https://github.com/slimtoolkit/slim) toolkit for minifying container images. *slim* is enabled by default and will, in addition to the `run` deployment image, produce an additional `:latest-slim`-tagged minified image. Note that the slimmed deployment image is stripped of every single thing not needed for executing the default launch command. The slimming process can be controlled via the `SLIM_BUILD_ARGS` configuration variable. + + ## Configuration Variables -> **Note** +> [!NOTE] > *GitHub Action input* | *GitLab CI environment variable* - **`additional-debs-file` | `ADDITIONAL_DEBS_FILE`** @@ -375,6 +397,10 @@ Create a folder `additional-files` in your `docker` folder (or configure a diffe - **`dev-image-tag` | `DEV_IMAGE_TAG`** Image tag of dev image *default:* `-dev` +- **`disable-ros-installation` | `DISABLE_ROS_INSTALLATION`** + Disable automatic installation of `ros-$ROS_DISTRO-ros-core` package + *e.g., if ROS is already installed in `base-image` and package is not available for the OS* + *default:* `false` - **`-` | `DOCKER_ROS_GIT_REF`** Git reference of *docker-ros* to run in CI *default:* `main` @@ -420,6 +446,9 @@ Create a folder `additional-files` in your `docker` folder (or configure a diffe - **`enable-singlearch-push` | `ENABLE_SINGLEARCH_PUSH`** Enable push of single arch images with `-amd64`/`-arm64` postfix *default:* `false` +- **`enable-slim` | `ENABLE_SLIM`** + Enable an extra slimmed run image via [slim](https://github.com/slimtoolkit/slim) (only if `run` stage is targeted) + *default:* `true` - **`git-https-password` | `GIT_HTTPS_PASSWORD`** Password for cloning private Git repositories via HTTPS *default:* `${{ github.token }}` | `$CI_JOB_TOKEN` @@ -455,11 +484,20 @@ Create a folder `additional-files` in your `docker` folder (or configure a diffe - **`rmw-implementation` | `RMW_IMPLEMENTATION`** ROS 2 middleware implementation *default:* `rmw_cyclonedds_cpp` - *supported values:* `rmw_fastrtps_cpp`, `rmw_cyclonedds_cpp`, `rmw_gurumdds_cpp`, ... + *supported values:* `rmw_zenoh_cpp`, `rmw_fastrtps_cpp`, `rmw_cyclonedds_cpp`, `rmw_gurumdds_cpp`, ... - **`ros-distro` | `ROS_DISTRO`** ROS Distro *required if ROS is not installed in `base-image`* *supported values:* `rolling`, ..., `noetic`, ... +- **`slim-build-args` | `SLIM_BUILD_ARGS`** + [Arguments to `slim build`](https://github.com/slimtoolkit/slim?tab=readme-ov-file#build-command-options) (except for `--target` and `--tag`) + *default:* `--sensor-ipc-mode proxy --continue-after=10 --show-clogs --http-probe=false` +- **`slim-image-name` | `SLIM_IMAGE_NAME`** + Image name of slim run image + *default:* `` +- **`slim-image-tag` | `SLIM_IMAGE_TAG`** + Image tag of slim run image + *default:* `-slim` - **`target` | `TARGET`** Target stage of Dockerfile (comma-separated list) *default:* `run` diff --git a/action.yml b/action.yml index 3cf00ec..1bb0601 100644 --- a/action.yml +++ b/action.yml @@ -1,5 +1,8 @@ name: "docker-ros" description: "docker-ros automatically builds development and deployment Docker images for your ROS-based repositories." +branding: + color: blue + icon: package inputs: @@ -27,6 +30,7 @@ inputs: dev-image-name: description: "Image name of dev image" + default: ghcr.io/${{ github.repository }} dev-image-tag: description: "Image tag of dev image" @@ -37,6 +41,13 @@ inputs: build-image-tag: description: "Image tag of build image" + slim-image-name: + description: "Image name of slim run image" + default: ghcr.io/${{ github.repository }} + + slim-image-tag: + description: "Image tag of slim run image" + build-context: description: "Build context of Docker build process" default: ${{ github.workspace }} @@ -60,6 +71,10 @@ inputs: ros-distro: description: "ROS Distro (required if ROS is not installed in `base-image`)" + disable-ros-installation: + description: "Disable automatic installation of `ros-$ROS_DISTRO-ros-core` package, e.g., if ROS is already installed in `base-image` and package is not available for the OS" + default: false + git-https-server: description: "Server URL (without protocol) for cloning private Git repositories via HTTPS" default: "github.com" @@ -118,6 +133,14 @@ inputs: description: "Enable industrial_ci" default: false + enable-slim: + description: "Enable an extra slimmed run image via slim (only if run stage is targeted)" + default: true + + slim-build-args: + description: "Arguments to `slim build` (except for `--target` and `--tag`)" + default: '--sensor-ipc-mode proxy --continue-after=10 --show-clogs --http-probe=false' + enable-singlearch-push: description: "Enable push of single arch images with [-amd64|-arm64] postfix" default: false @@ -208,6 +231,12 @@ runs: with: string: ${{ inputs.build-image-name }} + - name: Enforce lower-case slim image name + id: slim-image-name + uses: ASzc/change-string-case-action@v6 + with: + string: ${{ inputs.slim-image-name }} + - name: Build images id: build-images shell: bash @@ -225,6 +254,7 @@ runs: CUSTOM_SCRIPT_FILE: ${{ inputs.custom-script-file }} DEV_IMAGE_NAME: ${{ steps.dev-image-name.outputs.lowercase }} DEV_IMAGE_TAG: ${{ inputs.dev-image-tag }} + DISABLE_ROS_INSTALLATION: ${{ inputs.disable-ros-installation }} ENABLE_CONTINUE_BUILD_DESPITE_ERRORS: ${{ inputs.enable-continue-build-despite-errors }} ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS: ${{ inputs.enable-continue-rosdep-install-despite-errors }} ENABLE_RECURSIVE_ADDITIONAL_DEBS: ${{ inputs.enable-recursive-additional-debs }} @@ -233,6 +263,7 @@ runs: ENABLE_RECURSIVE_CUSTOM_SCRIPT: ${{ inputs.enable-recursive-custom-script }} ENABLE_RECURSIVE_VCS_IMPORT: ${{ inputs.enable-recursive-vcs-import }} ENABLE_ROS1_DEVEL_SPACE: ${{ inputs.enable-ros1-devel-space }} + ENABLE_SLIM: ${{ inputs.enable-slim }} GIT_HTTPS_PASSWORD: ${{ inputs.git-https-password }} GIT_HTTPS_SERVER: ${{ inputs.git-https-server }} GIT_HTTPS_USER: ${{ inputs.git-https-user }} @@ -243,6 +274,9 @@ runs: PLATFORM: ${{ inputs.platform }} RMW_IMPLEMENTATION: ${{ inputs.rmw-implementation }} ROS_DISTRO: ${{ inputs.ros-distro }} + SLIM_BUILD_ARGS: ${{ inputs.slim-build-args }} + SLIM_IMAGE_NAME: ${{ steps.slim-image-name.outputs.lowercase }} + SLIM_IMAGE_TAG: ${{ inputs.slim-image-tag }} TARGET: ${{ inputs.target }} VCS_IMPORT_FILE: ${{ inputs.vcs-import-file }} @@ -256,7 +290,7 @@ runs: uses: ros-industrial/industrial_ci@master env: ADDITIONAL_DEBS: git - AFTER_INIT_EMBED: '[[ -n ${{ inputs.git-https-server }} ]] && git config --global url.https://${{ inputs.git-https-user }}:${{ inputs.git-https-password }}@${{ inputs.git-https-server }}.insteadOf https://${{ inputs.git-https-server }}' + AFTER_INIT_EMBED: '[[ "$RMW_IMPLEMENTATION" == "rmw_zenoh_cpp" ]] && export UNDERLAY="/opt/ws_rmw_zenoh/install" ; [[ -n ${{ inputs.git-https-server }} ]] && git config --global url.https://${{ inputs.git-https-user }}:${{ inputs.git-https-password }}@${{ inputs.git-https-server }}.insteadOf https://${{ inputs.git-https-server }}' DOCKER_IMAGE: ${{ steps.build-images.outputs.INDUSTRIAL_CI_IMAGE }} DOCKER_PULL: false DOCKER_RUN_OPTS: -u root:root @@ -276,6 +310,8 @@ runs: working-directory: ${{ inputs.build-context }} run: docker/docker-ros/scripts/ci.sh env: + _ENABLE_IMAGE_PUSH: true + _IMAGE_POSTFIX: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) && format('_{0}_ci', steps.slugify-ref-name.outputs.slug) || '' }} ADDITIONAL_DEBS_FILE: ${{ inputs.additional-debs-file }} ADDITIONAL_FILES_DIR: ${{ inputs.additional-files-dir }} ADDITIONAL_PIP_FILE: ${{ inputs.additional-pip-file }} @@ -285,8 +321,9 @@ runs: BUILD_IMAGE_TAG: ${{ inputs.build-image-tag }} COMMAND: ${{ inputs.command }} CUSTOM_SCRIPT_FILE: ${{ inputs.custom-script-file }} - DEV_IMAGE_NAME: ${{ inputs.dev-image-name }} + DEV_IMAGE_NAME: ${{ steps.dev-image-name.outputs.lowercase }} DEV_IMAGE_TAG: ${{ inputs.dev-image-tag }} + DISABLE_ROS_INSTALLATION: ${{ inputs.disable-ros-installation }} ENABLE_CONTINUE_BUILD_DESPITE_ERRORS: ${{ inputs.enable-continue-build-despite-errors }} ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS: ${{ inputs.enable-continue-rosdep-install-despite-errors }} ENABLE_RECURSIVE_ADDITIONAL_DEBS: ${{ inputs.enable-recursive-additional-debs }} @@ -296,6 +333,7 @@ runs: ENABLE_RECURSIVE_VCS_IMPORT: ${{ inputs.enable-recursive-vcs-import }} ENABLE_ROS1_DEVEL_SPACE: ${{ inputs.enable-ros1-devel-space }} ENABLE_SINGLEARCH_PUSH: ${{ inputs.enable-singlearch-push }} + ENABLE_SLIM: ${{ inputs.enable-slim }} GIT_HTTPS_PASSWORD: ${{ inputs.git-https-password }} GIT_HTTPS_SERVER: ${{ inputs.git-https-server }} GIT_HTTPS_USER: ${{ inputs.git-https-user }} @@ -306,10 +344,11 @@ runs: PLATFORM: ${{ inputs.platform }} RMW_IMPLEMENTATION: ${{ inputs.rmw-implementation }} ROS_DISTRO: ${{ inputs.ros-distro }} + SLIM_BUILD_ARGS: ${{ inputs.slim-build-args }} + SLIM_IMAGE_NAME: ${{ steps.slim-image-name.outputs.lowercase }} + SLIM_IMAGE_TAG: ${{ inputs.slim-image-tag }} TARGET: ${{ inputs.target }} VCS_IMPORT_FILE: ${{ inputs.vcs-import-file }} - _ENABLE_IMAGE_PUSH: true - _IMAGE_POSTFIX: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) && format('_{0}_ci', steps.slugify-ref-name.outputs.slug) || '' }} - name: Push images (as latest) if: ${{ inputs.enable-push-as-latest == 'true' }} @@ -317,6 +356,8 @@ runs: working-directory: ${{ inputs.build-context }} run: docker/docker-ros/scripts/ci.sh env: + _ENABLE_IMAGE_PUSH: true + _IMAGE_POSTFIX: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) && format('_{0}_ci', steps.slugify-ref-name.outputs.slug) || '' }} ADDITIONAL_DEBS_FILE: ${{ inputs.additional-debs-file }} ADDITIONAL_FILES_DIR: ${{ inputs.additional-files-dir }} ADDITIONAL_PIP_FILE: ${{ inputs.additional-pip-file }} @@ -326,8 +367,9 @@ runs: BUILD_IMAGE_TAG: ${{ inputs.build-image-tag }} COMMAND: ${{ inputs.command }} CUSTOM_SCRIPT_FILE: ${{ inputs.custom-script-file }} - DEV_IMAGE_NAME: ${{ inputs.dev-image-name }} + DEV_IMAGE_NAME: ${{ steps.dev-image-name.outputs.lowercase }} DEV_IMAGE_TAG: latest-dev + DISABLE_ROS_INSTALLATION: ${{ inputs.disable-ros-installation }} ENABLE_CONTINUE_BUILD_DESPITE_ERRORS: ${{ inputs.enable-continue-build-despite-errors }} ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS: ${{ inputs.enable-continue-rosdep-install-despite-errors }} ENABLE_RECURSIVE_ADDITIONAL_DEBS: ${{ inputs.enable-recursive-additional-debs }} @@ -337,6 +379,7 @@ runs: ENABLE_RECURSIVE_VCS_IMPORT: ${{ inputs.enable-recursive-vcs-import }} ENABLE_ROS1_DEVEL_SPACE: ${{ inputs.enable-ros1-devel-space }} ENABLE_SINGLEARCH_PUSH: ${{ inputs.enable-singlearch-push }} + ENABLE_SLIM: ${{ inputs.enable-slim }} GIT_HTTPS_PASSWORD: ${{ inputs.git-https-password }} GIT_HTTPS_SERVER: ${{ inputs.git-https-server }} GIT_HTTPS_USER: ${{ inputs.git-https-user }} @@ -347,7 +390,8 @@ runs: PLATFORM: ${{ inputs.platform }} RMW_IMPLEMENTATION: ${{ inputs.rmw-implementation }} ROS_DISTRO: ${{ inputs.ros-distro }} + SLIM_BUILD_ARGS: ${{ inputs.slim-build-args }} + SLIM_IMAGE_NAME: ${{ steps.slim-image-name.outputs.lowercase }} + SLIM_IMAGE_TAG: latest-slim TARGET: ${{ inputs.target }} VCS_IMPORT_FILE: ${{ inputs.vcs-import-file }} - _ENABLE_IMAGE_PUSH: true - _IMAGE_POSTFIX: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) && format('_{0}_ci', steps.slugify-ref-name.outputs.slug) || '' }} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 835a8cc..9911584 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,7 +1,7 @@ ARG BASE_IMAGE ############ dependencies ###################################################### -FROM ${BASE_IMAGE} as dependencies +FROM ${BASE_IMAGE} AS dependencies USER root SHELL ["/bin/bash", "-c"] @@ -18,25 +18,27 @@ ENV ROS_DISTRO=${ROS_DISTRO} RUN test -n "$ROS_DISTRO" || (echo "missing build-arg: ROS_DISTRO" && false) RUN apt-get update && \ apt-get install -y curl gnupg && \ - if [[ "$ROS_DISTRO" == "noetic" ]]; then \ + if [[ "$ROS_DISTRO" == "noetic" ]] && ! cat /etc/apt/sources.list /etc/apt/sources.list.d/* | grep "http://packages.ros.org/ros/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main"; then \ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 && \ echo "deb http://packages.ros.org/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros1-latest.list ; \ - else \ + elif ! cat /etc/apt/sources.list /etc/apt/sources.list.d/* | grep "http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main"; then \ curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg && \ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null ; \ fi && \ rm -rf /var/lib/apt/lists/* # install ROS bootstrapping tools +ARG DISABLE_ROS_INSTALLATION="false" RUN apt-get update && \ apt-get install -y \ git \ python3-rosdep \ - python3-vcstool \ - ros-${ROS_DISTRO}-ros-core && \ + python3-vcstool && \ if [[ "$ROS_DISTRO" == "noetic" ]]; then \ - apt-get install -y \ - python3-catkin-tools ; \ + apt-get install -y python3-catkin-tools; \ + fi && \ + if [[ "$DISABLE_ROS_INSTALLATION" != "true" ]]; then \ + apt-get install -y ros-${ROS_DISTRO}-ros-core; \ fi && \ rm -rf /var/lib/apt/lists/* @@ -105,9 +107,9 @@ RUN echo "set -e" >> $WORKSPACE/.install-dependencies.sh && \ if [[ "$ROS_DISTRO" = "rolling" && "$OS" = "ubuntu:focal" ]]; then export OS="ubuntu:jammy"; fi && \ set -o pipefail && \ if [[ $ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS == 'true' ]]; then \ - ROS_PACKAGE_PATH=$(pwd):$ROS_PACKAGE_PATH rosdep install --os $OS -y --simulate --from-paths src --ignore-src -r | tee -a $WORKSPACE/.install-dependencies.sh ; \ + ROS_PACKAGE_PATH=$(pwd):$ROS_PACKAGE_PATH rosdep install --os $OS -y --simulate --from-paths src --ignore-src -r | sed -E "s/'apt-get install -y ([^']+)' \(alternative 1\/1\)/apt-get install -y \1/" | tee -a $WORKSPACE/.install-dependencies.sh ; \ else \ - ROS_PACKAGE_PATH=$(pwd):$ROS_PACKAGE_PATH rosdep install --os $OS -y --simulate --from-paths src --ignore-src | tee -a $WORKSPACE/.install-dependencies.sh ; \ + ROS_PACKAGE_PATH=$(pwd):$ROS_PACKAGE_PATH rosdep install --os $OS -y --simulate --from-paths src --ignore-src | sed -E "s/'apt-get install -y ([^']+)' \(alternative 1\/1\)/apt-get install -y \1/" | tee -a $WORKSPACE/.install-dependencies.sh ; \ fi && \ chmod +x $WORKSPACE/.install-dependencies.sh && \ rm -rf /var/lib/apt/lists/* @@ -179,10 +181,10 @@ ENV ROS_DISTRO=${ROS_DISTRO} RUN test -n "$ROS_DISTRO" || (echo "missing build-arg: ROS_DISTRO" && false) RUN apt-get update && \ apt-get install -y curl gnupg && \ - if [[ "$ROS_DISTRO" == "noetic" ]]; then \ + if [[ "$ROS_DISTRO" == "noetic" ]] && ! cat /etc/apt/sources.list /etc/apt/sources.list.d/* | grep "http://packages.ros.org/ros/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main"; then \ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 && \ echo "deb http://packages.ros.org/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros1-latest.list ; \ - else \ + elif ! cat /etc/apt/sources.list /etc/apt/sources.list.d/* | grep "http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main"; then \ curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg && \ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null ; \ fi && \ @@ -193,14 +195,20 @@ ARG ADDITIONAL_FILES_DIR="docker/additional-files" ADD ${ADDITIONAL_FILES_DIR}* /docker-ros/additional-files/ # install essential build tools and dependencies for install script +ARG DISABLE_ROS_INSTALLATION="false" RUN apt-get update && \ apt-get install -y \ build-essential \ gosu \ python-is-python3 \ - python3-pip \ - ros-${ROS_DISTRO}-ros-core \ - && rm -rf /var/lib/apt/lists/* + python3-pip && \ + if [[ "$DISABLE_ROS_INSTALLATION" != "true" ]]; then \ + apt-get install -y ros-${ROS_DISTRO}-ros-core; \ + fi && \ + rm -rf /var/lib/apt/lists/* + +# configure pip +RUN python -m pip config --global set global.break-system-packages true # copy install script from dependencies stage COPY --from=dependencies $WORKSPACE/.install-dependencies.sh $WORKSPACE/.install-dependencies.sh @@ -226,7 +234,22 @@ RUN source /opt/ros/$ROS_DISTRO/setup.bash && \ ARG RMW_IMPLEMENTATION="rmw_cyclonedds_cpp" ENV RMW_IMPLEMENTATION=${RMW_IMPLEMENTATION} RUN source /opt/ros/$ROS_DISTRO/setup.bash && \ - if [[ "$ROS_VERSION" == "2" ]]; then \ + if [[ "$RMW_IMPLEMENTATION" == "rmw_zenoh_cpp" ]]; then \ + mkdir -p /opt/ws_rmw_zenoh/src && \ + git clone https://github.com/ros2/rmw_zenoh.git /opt/ws_rmw_zenoh/src/rmw_zenoh && \ + if [[ "$(lsb_release -r | awk '{print $2}')" == "22.04" ]]; then \ + git clone https://github.com/eProsima/Fast-CDR.git /opt/ws_rmw_zenoh/src/Fast-CDR ; \ + fi && \ + rosdep init || true && \ + rosdep update --rosdistro $ROS_DISTRO && \ + apt-get update && \ + cd /opt/ws_rmw_zenoh && \ + rosdep install -y --from-paths src --ignore-src --rosdistro $ROS_DISTRO && \ + rm -rf /var/lib/apt/lists/* && \ + source /opt/ros/${ROS_DISTRO}/setup.bash && \ + colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release && \ + echo "source /opt/ws_rmw_zenoh/install/setup.bash" >> ~/.bashrc ; \ + elif [[ "$ROS_VERSION" == "2" ]]; then \ apt-get update && \ RMW_PACKAGE=ros-$ROS_DISTRO-$(echo $RMW_IMPLEMENTATION | tr '_' '-') && \ apt-get install -y $RMW_PACKAGE && \ @@ -239,14 +262,14 @@ RUN echo "source /opt/ros/$ROS_DISTRO/setup.bash" >> ~/.bashrc && \ echo "[[ -f $WORKSPACE/install/setup.bash ]] && source $WORKSPACE/install/setup.bash" >> ~/.bashrc # set entrypoint -ENV TINI_VERSION v0.19.0 +ENV TINI_VERSION=v0.19.0 ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini RUN chmod +x /tini COPY docker/docker-ros/docker/entrypoint.sh / ENTRYPOINT ["/tini", "--", "/entrypoint.sh"] ############ dev ############################################################### -FROM dependencies-install as dev +FROM dependencies-install AS dev # copy contents of repository from dependencies stage COPY --from=dependencies $WORKSPACE/src $WORKSPACE/src @@ -254,13 +277,14 @@ COPY --from=dependencies $WORKSPACE/src $WORKSPACE/src CMD ["bash"] ############ build ############################################################# -FROM dev as build +FROM dev AS build # build ROS workspace ARG ENABLE_CONTINUE_BUILD_DESPITE_ERRORS="false" ARG ENABLE_ROS1_DEVEL_SPACE="false" RUN source /opt/ros/${ROS_DISTRO}/setup.bash && \ if [[ -x "$(command -v colcon)" ]]; then \ + [[ -f /opt/ws_rmw_zenoh/install/setup.bash ]] && source /opt/ws_rmw_zenoh/install/setup.bash && \ if [[ $ENABLE_CONTINUE_BUILD_DESPITE_ERRORS == 'true' ]]; then \ colcon build --continue-on-error --cmake-args -DCMAKE_BUILD_TYPE=Release || true ; \ else \ @@ -283,7 +307,7 @@ ENV DEFAULT_CMD=${COMMAND} CMD bash -c "${DEFAULT_CMD}" ############ run ############################################################### -FROM dependencies-install as run +FROM dependencies-install AS run # copy ROS install space from build stage COPY --from=build $WORKSPACE/install install diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 2456281..e31252c 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -3,25 +3,32 @@ set -e # source ROS workspace source /opt/ros/$ROS_DISTRO/setup.bash +[[ -f /opt/ws_rmw_zenoh/install/setup.bash ]] && source /opt/ws_rmw_zenoh/install/setup.bash [[ -f $WORKSPACE/devel/setup.bash ]] && source $WORKSPACE/devel/setup.bash [[ -f $WORKSPACE/install/setup.bash ]] && source $WORKSPACE/install/setup.bash # exec as dockeruser with configured UID/GID if [[ $DOCKER_UID && $DOCKER_GID ]]; then - groupadd -g $DOCKER_GID $DOCKER_USER - useradd -s /bin/bash \ - -u $DOCKER_UID \ - -g $DOCKER_USER \ - --create-home \ - --home-dir /home/$DOCKER_USER \ - --groups sudo,video \ - --password "$(openssl passwd -1 $DOCKER_USER)" \ - $DOCKER_USER && \ - touch /home/$DOCKER_USER/.sudo_as_admin_successful - cp /root/.bashrc /home/$DOCKER_USER - ln -s $WORKSPACE /home/$DOCKER_USER/ws - chown -R $DOCKER_USER:$DOCKER_USER $WORKSPACE - chown -R $DOCKER_USER:$DOCKER_USER /home/$DOCKER_USER + if ! getent group $DOCKER_GID > /dev/null 2>&1; then + groupadd -g $DOCKER_GID $DOCKER_USER + fi + if ! getent passwd $DOCKER_UID > /dev/null 2>&1; then + useradd -s /bin/bash \ + -u $DOCKER_UID \ + -g $DOCKER_GID \ + --create-home \ + --home-dir /home/$DOCKER_USER \ + --groups sudo,video \ + --password "$(openssl passwd -1 $DOCKER_USER)" \ + $DOCKER_USER && \ + touch /home/$DOCKER_USER/.sudo_as_admin_successful + cp /root/.bashrc /home/$DOCKER_USER + ln -s $WORKSPACE /home/$DOCKER_USER/ws + chown -h $DOCKER_UID:$DOCKER_GID $WORKSPACE /home/$DOCKER_USER/ws /home/$DOCKER_USER/.sudo_as_admin_successful + if [[ -d $WORKSPACE/src ]]; then + chown -R $DOCKER_USER:$DOCKER_USER $WORKSPACE/src + fi + fi [[ $(pwd) == "$WORKSPACE" ]] && cd /home/$DOCKER_USER/ws exec gosu $DOCKER_USER "$@" else diff --git a/scripts/build.sh b/scripts/build.sh index 6e5dd4f..4cd249e 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -22,6 +22,7 @@ build_image() { $(if [[ -n "${ADDITIONAL_PIP_FILE}" ]]; then echo "--build-arg ADDITIONAL_PIP_FILE=${ADDITIONAL_PIP_FILE}"; fi) \ $(if [[ -n "${BLACKLISTED_PACKAGES_FILE}" ]]; then echo "--build-arg BLACKLISTED_PACKAGES_FILE=${BLACKLISTED_PACKAGES_FILE}"; fi) \ $(if [[ -n "${CUSTOM_SCRIPT_FILE}" ]]; then echo "--build-arg CUSTOM_SCRIPT_FILE=${CUSTOM_SCRIPT_FILE}"; fi) \ + $(if [[ -n "${DISABLE_ROS_INSTALLATION}" ]]; then echo "--build-arg DISABLE_ROS_INSTALLATION=${DISABLE_ROS_INSTALLATION}"; fi) \ $(if [[ -n "${ENABLE_CONTINUE_BUILD_DESPITE_ERRORS}" ]]; then echo "--build-arg ENABLE_CONTINUE_BUILD_DESPITE_ERRORS=${ENABLE_CONTINUE_BUILD_DESPITE_ERRORS}"; fi) \ $(if [[ -n "${ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS}" ]]; then echo "--build-arg ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS=${ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS}"; fi) \ $(if [[ -n "${ENABLE_RECURSIVE_ADDITIONAL_DEBS}" ]]; then echo "--build-arg ENABLE_RECURSIVE_ADDITIONAL_DEBS=${ENABLE_RECURSIVE_ADDITIONAL_DEBS}"; fi) \ diff --git a/scripts/ci.sh b/scripts/ci.sh index 6ae27cb..46bac52 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -18,14 +18,19 @@ BUILD_IMAGE_NAME="${BUILD_IMAGE_NAME:-${IMAGE_NAME}}" BUILD_IMAGE_TAG="${BUILD_IMAGE_TAG:-${IMAGE_TAG}-build}" DEV_IMAGE_NAME="${DEV_IMAGE_NAME:-${IMAGE_NAME}}" DEV_IMAGE_TAG="${DEV_IMAGE_TAG:-${IMAGE_TAG}-dev}" +SLIM_IMAGE_NAME="${SLIM_IMAGE_NAME:-${IMAGE_NAME}}" +SLIM_IMAGE_TAG="${SLIM_IMAGE_TAG:-${IMAGE_TAG}-slim}" +_ENABLE_IMAGE_PUSH="${_ENABLE_IMAGE_PUSH:-false}" +_IMAGE_POSTFIX="${_IMAGE_POSTFIX:-""}" ADDITIONAL_DEBS_FILE="${ADDITIONAL_DEBS_FILE:-}" ADDITIONAL_FILES_DIR="${ADDITIONAL_FILES_DIR:-}" ADDITIONAL_PIP_FILE="${ADDITIONAL_PIP_FILE:-}" BLACKLISTED_PACKAGES_FILE="${BLACKLISTED_PACKAGES_FILE:-}" +BUILD_IMAGE="${BUILD_IMAGE_NAME}:${BUILD_IMAGE_TAG}" CUSTOM_SCRIPT_FILE="${CUSTOM_SCRIPT_FILE:-}" DEV_IMAGE="${DEV_IMAGE_NAME}:${DEV_IMAGE_TAG}" -BUILD_IMAGE="${BUILD_IMAGE_NAME}:${BUILD_IMAGE_TAG}" +DISABLE_ROS_INSTALLATION="${DISABLE_ROS_INSTALLATION:-}" ENABLE_CONTINUE_BUILD_DESPITE_ERRORS="${ENABLE_CONTINUE_BUILD_DESPITE_ERRORS:-}" ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS="${ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS:-}" ENABLE_RECURSIVE_ADDITIONAL_DEBS="${ENABLE_RECURSIVE_ADDITIONAL_DEBS:-}" @@ -35,6 +40,7 @@ ENABLE_RECURSIVE_CUSTOM_SCRIPT="${ENABLE_RECURSIVE_CUSTOM_SCRIPT:-}" ENABLE_RECURSIVE_VCS_IMPORT="${ENABLE_RECURSIVE_VCS_IMPORT:-}" ENABLE_ROS1_DEVEL_SPACE="${ENABLE_ROS1_DEVEL_SPACE:-}" ENABLE_SINGLEARCH_PUSH="${ENABLE_SINGLEARCH_PUSH:-false}" +ENABLE_SLIM="${ENABLE_SLIM:-true}" GIT_HTTPS_PASSWORD="${GIT_HTTPS_PASSWORD:-}" GIT_HTTPS_SERVER="${GIT_HTTPS_SERVER:-}" GIT_HTTPS_USER="${GIT_HTTPS_USER:-}" @@ -43,9 +49,9 @@ GIT_SSH_PRIVATE_KEY="${GIT_SSH_PRIVATE_KEY:-}" IMAGE="${IMAGE_NAME}:${IMAGE_TAG}" RMW_IMPLEMENTATION="${RMW_IMPLEMENTATION:-}" ROS_DISTRO="${ROS_DISTRO:-}" +SLIM_BUILD_ARGS="${SLIM_BUILD_ARGS:-'--sensor-ipc-mode proxy --continue-after=10 --show-clogs --http-probe=false'}" +SLIM_IMAGE="${SLIM_IMAGE_NAME}:${SLIM_IMAGE_TAG}" VCS_IMPORT_FILE="${VCS_IMPORT_FILE:-}" -_ENABLE_IMAGE_PUSH="${_ENABLE_IMAGE_PUSH:-false}" -_IMAGE_POSTFIX="${_IMAGE_POSTFIX:-""}" # write image name for industrial_ci to output (GitHub-only) if [[ -n "${GITHUB_ACTIONS}" ]]; then @@ -71,6 +77,12 @@ fi unset TARGET unset PLATFORM +# prepare slim +if [[ "${ENABLE_SLIM}" == "true" ]]; then + curl -L -o ds.tar.gz https://github.com/slimtoolkit/slim/releases/download/1.40.11/dist_linux.tar.gz + tar -xvf ds.tar.gz +fi + # loop over targets and platforms to build images for PLATFORM in "${PLATFORMS[@]}"; do for TARGET in "${TARGETS[@]}"; do @@ -83,4 +95,22 @@ for PLATFORM in "${PLATFORMS[@]}"; do IMAGE="${image}" build_image close_log_group done + + # slim image + if [[ "${ENABLE_SLIM}" == "true" && "${TARGET}" == "run" ]]; then + open_log_group "Slim image (${PLATFORM})" + image="${IMAGE}" + slim_image="${SLIM_IMAGE}" + [[ -n "${_IMAGE_POSTFIX}" ]] && image="${image}${_IMAGE_POSTFIX}" + [[ -n "${_IMAGE_POSTFIX}" ]] && slim_image="${slim_image}${_IMAGE_POSTFIX}" + [[ "${_ENABLE_IMAGE_PUSH}" != "true" || "${ENABLE_SINGLEARCH_PUSH}" == "true" ]] && image="${image}-${PLATFORM}" + [[ "${_ENABLE_IMAGE_PUSH}" != "true" || "${ENABLE_SINGLEARCH_PUSH}" == "true" ]] && slim_image="${slim_image}-${PLATFORM}" + cd dist_linux* + ./slim build --target "${image}" --tag "${slim_image}" ${SLIM_BUILD_ARGS} + if [[ "${_ENABLE_IMAGE_PUSH}" == "true" ]]; then + docker push "${slim_image}" + fi + cd - + close_log_group + fi done diff --git a/templates/README.template.md b/templates/README.template.md deleted file mode 100644 index 3b364b3..0000000 --- a/templates/README.template.md +++ /dev/null @@ -1,105 +0,0 @@ -# \ - -\ - -- [Nodes](#nodes) - - [\/\](#packagenode) -- [Usage of docker-ros Images](#usage-of-docker-ros-images) - - [Available Images](#available-images) - - [Default Command](#default-command) - - [Environment Variables](#environment-variables) - - [Launch Files](#launch-files) - - [Configuration Files](#configuration-files) - - [Additional Remarks](#additional-remarks) -- [Official Documentation](#official-documentation) - - -## Nodes - -| Package | Node | Description | -| --- | --- | --- | -| `` | `` | \ | - -### \/\ - -#### Subscribed Topics - - - -| Topic | Type | Description | -| --- | --- | --- | -| `` | `/msg/` | \ | - -#### Published Topics - - - -| Topic | Type | Description | -| --- | --- | --- | -| `` | `/msg/` | \ | - -#### Services - - - -| Service | Type | Description | -| --- | --- | --- | -| `` | `/srv/` | \ | - -#### Actions - - - -| Action | Type | Description | -| --- | --- | --- | -| `` | `/action/` | \ | - -#### Parameters - - - -| Parameter | Type | Description | -| --- | --- | --- | -| `` | `` | \ | - - -## Usage of docker-ros Images - -### Available Images - -| Tag | Description | -| --- | --- | -| `latest` | latest version | - -### Default Command - -```bash - -``` - -### Environment Variables - -| Variable | Description | -| --- | --- | -| `` | \ | - -### Launch Files - -| Package | File | Path | Description | -| --- | --- | --- | --- | -| `` | `.` | `` | \ | - -### Configuration Files - -| Package | File | Path | Description | -| --- | --- | --- | --- | -| `` | `.` | `` | \ | - -### Additional Remarks - -\- - - -## Official Documentation - -- \ diff --git a/templates/docker-compose.template.yml b/templates/docker-compose.template.yml deleted file mode 100644 index a623ba5..0000000 --- a/templates/docker-compose.template.yml +++ /dev/null @@ -1,52 +0,0 @@ -x-base-image: &base-image BASE_IMAGE # e.g. rwthika/ros2:humble -x-dev-image: &dev-image DEV_IMAGE # e.g. my-image:latest-dev -x-build-image: &build-image BUILD_IMAGE # e.g. my-image:latest-build -x-run-image: &run-image RUN_IMAGE # e.g. my-image:latest -x-command: &command COMMAND # e.g. ros2 run my_pkg my_node - -# ============================================================================== - -x-build-template: &build-template - dockerfile: ./docker/docker-ros/docker/Dockerfile - context: ../ - args: - BASE_IMAGE: *base-image - COMMAND: *command - ADDITIONAL_DEBS_FILE: $ADDITIONAL_DEBS_FILE - ADDITIONAL_FILES_DIR: $ADDITIONAL_FILES_DIR - ADDITIONAL_PIP_FILE: $ADDITIONAL_PIP_FILE - BLACKLISTED_PACKAGES_FILE: $BLACKLISTED_PACKAGES_FILE - VCS_IMPORT_FILE: $VCS_IMPORT_FILE - CUSTOM_SCRIPT_FILE: $CUSTOM_SCRIPT_FILE - ENABLE_CONTINUE_BUILD_DESPITE_ERRORS: $ENABLE_CONTINUE_BUILD_DESPITE_ERRORS - ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS: $ENABLE_CONTINUE_ROSDEP_INSTALL_DESPITE_ERRORS - ENABLE_RECURSIVE_ADDITIONAL_DEBS: $ENABLE_RECURSIVE_ADDITIONAL_DEBS - ENABLE_RECURSIVE_ADDITIONAL_PIP: $ENABLE_RECURSIVE_ADDITIONAL_PIP - ENABLE_RECURSIVE_BLACKLISTED_PACKAGES: $ENABLE_RECURSIVE_BLACKLISTED_PACKAGES - ENABLE_RECURSIVE_CUSTOM_SCRIPT: $ENABLE_RECURSIVE_CUSTOM_SCRIPT - ENABLE_RECURSIVE_VCS_IMPORT: $ENABLE_RECURSIVE_VCS_IMPORT - ENABLE_ROS1_DEVEL_SPACE: $ENABLE_ROS1_DEVEL_SPACE - GIT_HTTPS_PASSWORD: $GIT_HTTPS_PASSWORD - GIT_HTTPS_SERVER: $GIT_HTTPS_SERVER - GIT_HTTPS_USER: $GIT_HTTPS_USER - GIT_SSH_KNOWN_HOST_KEYS: $GIT_SSH_KNOWN_HOST_KEYS - GIT_SSH_PRIVATE_KEY: $GIT_SSH_PRIVATE_KEY - RMW_IMPLEMENTATION: $RMW_IMPLEMENTATION - ROS_DISTRO: $ROS_DISTRO - -services: - dev: - image: *dev-image - build: - target: dev - <<: *build-template - build: - image: *build-image - build: - target: build - <<: *build-template - run: - image: *run-image - build: - target: run - <<: *build-template \ No newline at end of file