diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..dc4c7a04 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +# Build artifacts +build/ +install/ +log/ + +# Version control +.gitmodules + +# Model weights (large files) +*.pt + +# Python cache +*.pyc +__pycache__/ +*.egg-info/ + +# IDE/Editor +.vscode/ +.idea/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db + +# Logs and temp files +*.log +nmealog.txt +*.gv diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 46470992..51471ea9 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -1,22 +1,31 @@ -name: Run setup and colcon build for Docker -on: push +name: Run setup for Docker + +on: + push: + branches: [main] + pull_request: + branches: [main] + types: [opened, synchronize, reopened] + jobs: - docker_setup_and_build_check: + build-test-push: + name: Build, Test and Push Docker Image runs-on: ubuntu-22.04 + steps: - - uses: actions/checkout@v4 - with: # added this, might fix a bug that's taken over 3 hours to find + - name: Checkout source code + uses: actions/checkout@v4 + with: + fetch-depth: 0 submodules: recursive - - name: build - run: | - docker compose build --no-cache - - name: start and exec into container - run: | # ensure a clean build tree inside container, then build - docker compose run --rm -T rover bash -lc 'rm -rf build install log && colcon build --symlink-install --packages-up-to arm_control' - - name: Cleanup - if: always() - run: | - docker compose down --remove-orphans || true + + - name: Build image + uses: docker/build-push-action@v5 + with: + context: . + load: true + tags: myapp:test + - name: Notify Discord (success) if: ${{ success() }} uses: appleboy/discord-action@v1.0.0 @@ -24,8 +33,10 @@ jobs: webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} message: | - Yipee!!! I'lll let you merge now ${{ github.actor }}. _good j*b_! || ${{ github.repository }} on `${{ github.ref_name }}` + Yipee!!! I'lll let you merge now ${{ github.actor }}. _good j*b_! || + ${{ github.repository }} on `${{ github.ref_name }}` ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + - name: Notify Discord (failure) if: ${{ failure() }} uses: appleboy/discord-action@v1.0.0 @@ -33,5 +44,5 @@ jobs: webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} message: | - poo you ${{ github.actor }}! Run it through chat rq to fix your bugs || + poo you ${{ github.actor }}! Run it through chat rq to fix your bugs || ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/Docker.md b/Docker.md index 49200751..bc74e722 100644 --- a/Docker.md +++ b/Docker.md @@ -32,7 +32,7 @@ The purpose of this is so that you don't have any dangling containers/images and ### 2. Build the image: ```bash -docker compose build +docker compose build ``` What happens here: @@ -43,7 +43,7 @@ What happens here: Extra commands: ```bash -docker compose build --no-cache # I use this often bc I'm terrible at managing stuff +docker compose build --no-cache docker compose ps # list running images/containers started with compose docker compose --version ``` @@ -58,7 +58,7 @@ What is happening here: Extra commands: ```bash -docker compose up -d # boots up a detached container (avoid non-detached version) +docker compose up -d # boots up a detached container (avoid non-detached version) docker compose prune # removes dangling pointers to any images/containers ``` diff --git a/DockerInstallation.md b/DockerInstallation.md new file mode 100644 index 00000000..3cc676c9 --- /dev/null +++ b/DockerInstallation.md @@ -0,0 +1,21 @@ +# Docker setup for RoverFlake2 + +Minimal installation setup for Docker. Ask ChatGPT first if you are having trouble (do NOT run random commands unless you know exactly what they do). If you still can't figure it out, ask Aaron. Be sure to review the docs if you require any extra commands outside of what is listed. + +### 1. Prerequisites +- Install Docker and Docker Compose on your machine +> docker --version +> docker compose version + +### 2.1 Build the image (AMD64 Architecture): +> docker build -t rover2025:rover +### 2.2 Build the image (ARM64 Architecture): +> docker buildx build --platform linux/amd64,linux/arm64 -t roverflake2:dev --push . + +### 3. Start a detached container +> docker compose --compatibility up rover -d +(the compatibility flag might not work on Windows and if so, just remove it) + +### 4. Go into an existing container +> docker compose exec rover bash +(don't forget to change the service if you are using a different compose container) diff --git a/Dockerfile b/Dockerfile index 9fe47d66..be163571 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,8 @@ # Create and enter container with 'docker compose run rover bash' # if you have anymore questions ask Aaron -# official base image in docs -FROM osrf/ros:humble-desktop +# official base image in docs (pinned to jammy for reproducibility) +FROM osrf/ros:humble-desktop-jammy # consistency with setup files ENV DEBIAN_FRONTEND=noninteractive @@ -11,8 +11,8 @@ ENV TZ=Etc/UTC ENV ROVERFLAKE_ROOT=/RoverFlake2 ENV RMW_IMPLEMENTATION=rmw_cyclonedds_cpp -# install base depenencies (recommend not to change if you want to add niche deps) -RUN apt-get update && apt-get install -y \ +# install base dependencies (recommend not to change if you want to add niche deps) +RUN apt-get update && apt-get install -y --no-install-recommends \ tzdata \ sudo \ curl \ @@ -28,7 +28,7 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* # common ROS package deps (use this for niche deps) -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ ros-humble-urdf \ ros-humble-image-transport \ ros-humble-cv-bridge \ @@ -37,18 +37,21 @@ RUN apt-get update && apt-get install -y \ ros-humble-rosidl-default-runtime \ && rm -rf /var/lib/apt/lists/* -# copy root into container WORKDIR $ROVERFLAKE_ROOT -COPY . $ROVERFLAKE_ROOT + +# copy setup scripts and package manifests first for better layer caching +COPY setup_scripts/ $ROVERFLAKE_ROOT/setup_scripts/ +COPY src/ $ROVERFLAKE_ROOT/src/ # run full setup to install dependencies inside the image (auto-confirm prompts) RUN yes | bash setup_scripts/setup_everything_common.sh -# copy and set entrypoint (runs setup) -COPY docker/entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh +# copy everything else (code changes invalidate from here, but deps are cached) +COPY . $ROVERFLAKE_ROOT + +# set entrypoint (already copied above) +RUN chmod +x docker/entrypoint.sh -# changed with COPY -ENTRYPOINT ["/entrypoint.sh"] +ENTRYPOINT ["/RoverFlake2/docker/entrypoint.sh"] CMD ["/bin/bash"] diff --git a/docker-compose.yml b/docker-compose.yml index f3029ff2..dbd34a7c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,3 +30,52 @@ services: environment: - ROVERFLAKE_ROOT=/RoverFlake2 network_mode: host + rover_gpu: # GUI support + NVIDIA GPU support + container_name: rover_gpu + image: roverflake2:gpu + working_dir: /RoverFlake2 + build: + context: . + dockerfile: Dockerfile + runtime: nvidia + environment: + - DISPLAY=${DISPLAY} + - XAUTHORITY=/tmp/.docker.xauth # auto accept + - ROVERFLAKE_ROOT=/RoverFlake2 + - NVIDIA_VISIBLE_DEVICES=all + - NVIDIA_DRIVER_CAPABILITIES=all + - __GLX_VENDOR_LIBRARY_NAME=nvidia + volumes: + - ./:/RoverFlake2 + - /tmp/.X11-unix:/tmp/.X11-unix + - /tmp/.docker.xauth:/tmp/.docker.xauth + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: [gpu] + tty: true + stdin_open: true + network_mode: host + rover_x11: # Do not use if you don't have a nvidia GPU with supported cuda cores + build: + context: . + dockerfile: Dockerfile + image: roverflake2:dev + container_name: rover_dev + working_dir: /RoverFlake2 + tty: true + stdin_open: true + volumes: # Purpose: docker env watches for changes in repo and updates + # preferred method is to specify a directory + # e.g. '- ./node_practice:/RoverFlake2/node_practice' + # Bind-mount the whole repo into the container + - ./:/RoverFlake2 + - /tmp/.X11-unix:/tmp/.X11-unix # GUI compatibility + environment: + - DISPLAY=${DISPLAY} + - ROVERFLAKE_ROOT=/RoverFlake2 + - MUJOCO_GL=glfw # or egl (headless GUI) + network_mode: host diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh old mode 100644 new mode 100755 diff --git a/setup_scripts/submodule_update.sh b/setup_scripts/submodule_update.sh index 5b5110f0..7024f469 100755 --- a/setup_scripts/submodule_update.sh +++ b/setup_scripts/submodule_update.sh @@ -1 +1,7 @@ +# required for docker build +if [ ! -d "${ROVERFLAKE_ROOT}/.git" ]; then + echo "Not a git repository, skipping submodule update" + exit 0 +fi + git submodule update --init --recursive