Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ddc6ae4
add: user creation in entrypoint
AntoineBlanot Jul 18, 2025
c416dc8
Create default user in the docker build WIP
AntoineBlanot Jul 22, 2025
2640e42
update: remove user creation
AntoineBlanot Jul 29, 2025
b8fc361
update docker
AntoineBlanot Jul 29, 2025
0d7df14
add: python3-vcstool
AntoineBlanot Jul 29, 2025
34c2329
update entrypoint
AntoineBlanot Jul 30, 2025
093ecc9
fix: set rmw to cyclonedds by default to allow intra-user communicati…
AntoineBlanot Jul 30, 2025
53e82ab
typo
AntoineBlanot Jul 30, 2025
730ea1a
add: workflow to push docker images to ghcr
AntoineBlanot Jul 31, 2025
bb0c8b1
typo: worflow revision
AntoineBlanot Jul 31, 2025
eb3a785
typo: fix workflow
AntoineBlanot Jul 31, 2025
32e779e
update: haru-os image
AntoineBlanot Aug 1, 2025
da3faa6
typo: fix
AntoineBlanot Aug 1, 2025
3f11df9
add: wip haru-simulator (only haru systems work)
AntoineBlanot Aug 1, 2025
241c662
update: working unity-app
AntoineBlanot Aug 1, 2025
d8dd334
update: build and push haru-simulator to ghcr
AntoineBlanot Aug 1, 2025
808bb48
fix: build haru-simulator from arg base image name
AntoineBlanot Aug 1, 2025
1d0f0ab
typo: base image name from ghcr
AntoineBlanot Aug 1, 2025
dbf2a40
typo: docker linter
AntoineBlanot Aug 1, 2025
5cb2a34
add: web server
AntoineBlanot Aug 1, 2025
e8bee18
update: workflow secrets
AntoineBlanot Aug 1, 2025
a127361
update: remove audio device id
AntoineBlanot Aug 4, 2025
01aab6c
add: cyclone config for more paricipants as limit was reached
AntoineBlanot Aug 6, 2025
cffca8e
fix: cyclonedss config
AntoineBlanot Aug 6, 2025
c56a4b7
add: disable multicast on cyclonedds (need to set IP manually) (not f…
AntoineBlanot Aug 7, 2025
e537dea
add: working setup with zenoh as middleware. check router thought (no…
AntoineBlanot Aug 8, 2025
d80a993
disable shm transport for containers communication
AntoineBlanot Aug 12, 2025
9561f0f
typo: branch master instead of main
AntoineBlanot Aug 12, 2025
4a122dc
typo: update token var
AntoineBlanot Aug 12, 2025
74fb4d0
Update docker-publish.yaml
AntoineBlanot Aug 14, 2025
f89a6d0
Update docker-publish.yaml
AntoineBlanot Aug 14, 2025
4eee018
update: haru-simulator image uses .repos file
AntoineBlanot Aug 14, 2025
20c90dd
fix: typo in Dockerfile
AntoineBlanot Aug 14, 2025
4c03e3e
fix: typo in Dockerfile
AntoineBlanot Aug 14, 2025
b93b6d1
update: use CD_TOKEN to write private repos
AntoineBlanot Aug 14, 2025
dbbbf91
update: change action runner to self-hosted
AntoineBlanot Aug 14, 2025
041b295
update: revert to ubuntu-latest runner
AntoineBlanot Aug 14, 2025
dba3281
typo: fix docker env
AntoineBlanot Aug 15, 2025
5cde479
typo: change docker tag from ros2 to local
AntoineBlanot Sep 16, 2025
6d91fa6
add: control audio device from env variable
AntoineBlanot Sep 17, 2025
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
8 changes: 6 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# DISPLAY
DISPLAY=${DISPLAY}
DISPLAY=${DISPLAY:-=:0}

# AUDIO
AUDIO_CARD=0

# CUDA
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=all

# ROS
ROS_DOMAIN_ID=0
ROS_DOMAIN_ID=99
RMW_IMPLEMENTATION=rmw_fastrtps_cpp
82 changes: 82 additions & 0 deletions .github/workflows/docker-publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Build and Push Docker Images

on:
push:
branches:
- '*'
tags:
- '*'

jobs:
build-and-push:
name: Build and Push to GHCR
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

strategy:
matrix:
component: [haru-os, haru-simulator]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.CD_TOKEN }}

- name: Set variables
id: vars
run: |
OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')

# Tag with branch name or GitHub tag
if [[ "${GITHUB_REF}" == refs/heads/* ]]; then
REF_TYPE="branch"
TAG=$(echo "${GITHUB_REF#refs/heads/}" | tr '/' '-' | tr '[:upper:]' '[:lower:]')
elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then
REF_TYPE="tag"
TAG=$(echo "${GITHUB_REF#refs/tags/}" | tr '/' '-' | tr '[:upper:]' '[:lower:]')
else
echo "Unsupported ref: ${GITHUB_REF}"
exit 1
fi

echo "owner=$OWNER" >> $GITHUB_OUTPUT
echo "ref_type=$REF_TYPE" >> $GITHUB_OUTPUT
echo "tag=$TAG" >> $GITHUB_OUTPUT

- name: Build and push ${{ matrix.component }} image
uses: docker/build-push-action@v5
with:
context: ./${{ matrix.component }}
file: ./${{ matrix.component }}/Dockerfile
push: true
tags: |
ghcr.io/${{ steps.vars.outputs.owner }}/${{ matrix.component }}:${{ steps.vars.outputs.tag }}
build-args: |
CLONE_METHOD=https
BASE_IMAGE=ghcr.io/haru-project/haru-os:${{ steps.vars.outputs.tag }}
secrets: |
github_token=${{ secrets.CD_TOKEN }}

- name: Tag and push :latest if master
if: steps.vars.outputs.ref_type == 'branch' && steps.vars.outputs.tag == 'master'
uses: docker/build-push-action@v5
with:
context: ./${{ matrix.component }}
file: ./${{ matrix.component }}/Dockerfile
push: true
tags: |
ghcr.io/${{ steps.vars.outputs.owner }}/${{ matrix.component }}:latest
build-args: |
CLONE_METHOD=https
BASE_IMAGE=ghcr.io/haru-project/haru-os:latest
secrets: |
github_token=${{ secrets.CD_TOKEN }}
40 changes: 28 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,49 @@ Install the [Docker Engine](https://docs.docker.com/engine/install/ubuntu/) and
For CUDA support, also install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installing-the-nvidia-container-toolkit).

## Setup
Set ROS variable with:
```
export ROS_DOMAIN_ID=xxx
```

Allow Docker GUI access:
```
xhost +local:root
xhost +local:docker
```

## Images and Applications

### Haru-OS
```
docker build --rm -t haru/haru-os:ros2 -f haru-os/Dockerfile ./haru-os
docker build --rm -t haru/haru-os:local -f haru-os/Dockerfile ./haru-os
```

Run:
```
docker run -it --rm --name haru-os --gpus all \
--network host --ipc host \
docker run -it --rm --name haru-os \
--network host --ipc host --gpus all \
--env-file .env.example \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e DISPLAY=${DISPLAY} -e ROS_DOMAIN_ID=${ROS_DOMAIN_ID} \
haru/haru-os:ros2
haru/haru-os:local
```

Or compose: (recommended)
```
docker compose -f docker-compose-haru.yaml --env-file .env up
docker compose -f docker-compose-haru.yaml --env-file .env.example up
```

### Haru-Simulator
```
docker build --rm --ssh default=$SSH_AUTH_SOCK -t haru/haru-simulator:local -f haru-simulator/Dockerfile ./haru-simulator
# or docker build --rm --secret id=github_token,src=$GITHUB_TOKEN -t haru/haru-simulator:local -f haru-simulator/Dockerfile ./haru-simulator
```

Run:
```
docker run -it --rm --name haru-os \
--network host --ipc host --gpus all \
--env-file .env.example \
--device /dev/snd \
-v /tmp/.X11-unix:/tmp/.X11-unix \
haru/haru-simulator:local
```

Or compose: (recommended)
```
docker compose -f docker-compose-simulator.yaml --env-file .env.example up
```
51 changes: 30 additions & 21 deletions docker-compose-haru.yaml
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
name: haru
name: haru-os

services:
pub-root:
image: haru/haru-os:local
command: ["ros2", "topic", "pub", "/root", "std_msgs/msg/String", "{data: Hello from root}"]
env_file: .env.example
network_mode: host
ipc: host
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix

pub-user:
image: haru/haru-os:local
user: 1000:1000
command: ["ros2", "topic", "pub", "/user", "std_msgs/msg/String", "{data: Hello from user}"]
env_file: .env.example
network_mode: host
ipc: host
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix

test-publisher:
image: haru/haru-os:ros2
entrypoint: ["/entrypoint.sh"]
command: ["ros2", "topic", "pub", "-r", "1", "/hello", "std_msgs/msg/String", "data: 'Hello from Docker'"]
environment:
- DISPLAY=${DISPLAY}
- ROS_DOMAIN_ID=${ROS_DOMAIN_ID}
echo-root:
image: haru/haru-os:local
command: ["ros2", "topic", "echo", "/user"]
env_file: .env.example
network_mode: host
ipc: host
devices:
- /dev/snd
- /dev/bus/usb
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
restart: on-failure

rqt:
image: haru/haru-os:ros2
entrypoint: ["/entrypoint.sh"]
command: ["rqt"]
environment:
- DISPLAY=${DISPLAY}
- ROS_DOMAIN_ID=${ROS_DOMAIN_ID}
echo-user:
image: haru/haru-os:local
user: 1000:1000
command: ["ros2", "topic", "echo", "/root"]
env_file: .env.example
network_mode: host
ipc: host
devices:
- /dev/snd
- /dev/bus/usb
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
restart: on-failure
100 changes: 26 additions & 74 deletions docker-compose-simulator.yaml
Original file line number Diff line number Diff line change
@@ -1,84 +1,36 @@
name: simulator
name: haru-simulator

services:
ros-simulator:
image: haru-simulator
entrypoint: [ "/entrypoint.sh" ]
command: [ "/bin/bash", "-c", "roslaunch haru_unity unity_app_launcher.launch && tail -f /dev/null" ]
environment:
- DISPLAY=${DISPLAY}
- NVIDIA_DRIVER_CAPABILITIES=all
unity-app:
image: haru/haru-simulator:local
command: ["/bin/bash", "-c", "export ROS_IP=$(hostname -I | awk '{print $1}') && ros2 launch haru_unity unity_app_launcher_launch.py && tail -f /dev/null"]
env_file: .env.example
network_mode: host
ipc: host
devices:
- /dev/snd
- /dev/bus/usb
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
runtime: nvidia

ros-publisher:
image: haru-os
entrypoint: [ "/entrypoint.sh" ]
command: [ "rostopic", "pub", "/hello", "std_msgs/String", "data: 'Hello from Docker'", "-r", "1" ]
environment:
- DISPLAY=${DISPLAY}
network_mode: host
devices:
- /dev/snd
- /dev/bus/usb
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix

ros-publisher-cuda:
image: haru-os-cuda
entrypoint: [ "/entrypoint.sh" ]
command: [ "rostopic", "pub", "/hello_cuda", "std_msgs/String", "data: 'Hello from Docker with CUDA'", "-r", "1" ]
environment:
- DISPLAY=${DISPLAY}
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]

web-server:
image: haru/haru-simulator:local
working_dir: /app/haru2_web/
command: ["/bin/bash", "-c", "cd haru_web && \
../.venv/bin/python3 -m streamlit run Home.py \
--server.port 7000 \
--server.address 0.0.0.0 \
--server.headless true \
--server.baseUrlPath '/haru_web'",
]
env_file: .env.example
network_mode: host
devices:
- /dev/snd
- /dev/bus/usb
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
runtime: nvidia

ros-listener:
image: haru-os
entrypoint: [ "/entrypoint.sh" ]
command: [ "rostopic", "echo", "/hello" ]
environment:
- DISPLAY=${DISPLAY}
network_mode: host
devices:
- /dev/snd
- /dev/bus/usb
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix

ros-listener-cuda:
image: haru-os-cuda
entrypoint: [ "/entrypoint.sh" ]
command: [ "rostopic", "echo", "/hello_cuda" ]
environment:
- DISPLAY=${DISPLAY}
network_mode: host
devices:
- /dev/snd
- /dev/bus/usb
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
runtime: nvidia

ros-rqt:
image: haru-os
entrypoint: [ "/entrypoint.sh" ]
command: [ "rqt" ]
environment:
- DISPLAY=${DISPLAY}
network_mode: host
devices:
- /dev/snd
- /dev/bus/usb
ipc: host
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
Loading