From 74c633cf75039b4a59c105fe7caa8a7d5e97207b Mon Sep 17 00:00:00 2001 From: Andy Alt Date: Thu, 21 Nov 2024 07:00:22 -0600 Subject: [PATCH] Added Dockerfile and workflow (#8) * Added Dockerfile and workflow Closes #7 * Usermod builder * Update the docs, use entrypoint.sh * Remove duplicate build * Simplify --------- Co-authored-by: KaruroChori --- .github/workflows/docker-test.yml | 30 +++++++ .github/workflows/docker.yml | 40 +++++++++ .gitignore | 5 +- docker/Dockerfile | 41 +++++++++ docker/README.md | 139 ++++++++++++++++++++++++++++++ docker/default-entry.sh | 12 +++ docker/docker-compose.yml | 37 ++++++++ docker/main_entry.sh | 20 +++++ docker/shell-entry.sh | 6 ++ 9 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/docker-test.yml create mode 100644 .github/workflows/docker.yml create mode 100644 docker/Dockerfile create mode 100644 docker/README.md create mode 100755 docker/default-entry.sh create mode 100644 docker/docker-compose.yml create mode 100755 docker/main_entry.sh create mode 100755 docker/shell-entry.sh diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml new file mode 100644 index 00000000..0c118c60 --- /dev/null +++ b/.github/workflows/docker-test.yml @@ -0,0 +1,30 @@ +name: Test Build-Env Docker Image + +on: + pull_request: + branches: master + paths: + - '**Dockerfile' + - '**docker.yml' + +jobs: + build-test-env-image: + runs-on: ubuntu-latest + env: + SOURCE_ROOT: ${{ github.workspace }} + IMAGE: test-image + ENTRYPOINT: ${{ github.workspace }}/docker/default-entry.sh + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: sudo apt install -y docker-compose + + - name: Build Docker image + run: docker build -t $IMAGE -f docker/Dockerfile ./docker + + - name: Run commands in Docker container + run: | + export HOSTUID=$(id -u) + export HOSTGID=$(id -g) + docker-compose -f docker/docker-compose.yml run --rm dev diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..0e500bab --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,40 @@ +name: Build-Env Docker Image + +on: + push: + branches: master + paths: + - '**Dockerfile' + - '**docker.yml' +# workflow_dispatch: +# schedule: +# - cron: '30 11 20 */3 *' + +env: + REGISTRY_IMAGE: ghcr.io/${{ github.repository_owner }}/vs-fltk + +jobs: + build-env-image: + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + file: ./Dockerfile + platforms: ${{ matrix.platform }} + cache-from: type=registry,ref=${{ env.REGISTRY_IMAGE }}:build-env-buildcache + cache-to: type=registry,ref=${{ env.REGISTRY_IMAGE }}:build-env-buildcache,mode=max diff --git a/.gitignore b/.gitignore index 04ae98a5..9aac128b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,7 @@ subprojects/* /bun.lockb /private /logs -/.flatpak-builder \ No newline at end of file +/.flatpak-builder + +# Contains variables specific for the user +/docker/.env diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..4bf43172 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,41 @@ +FROM debian:trixie-slim + +ARG DEBIAN_FRONTEND=noninteractive +ENV DEBIAN_FRONTEND=$DEBIAN_FRONTEND + +RUN \ + apt update && apt upgrade -y && \ + apt install -y \ + build-essential \ + ca-certificates \ + clang-19 \ + cmake \ + curl \ + freeglut3-dev \ + git \ + libpng-dev \ + libsqlite3-0 \ + libsqlitecpp-dev \ + libtcc-dev \ + lsb-release \ + meson \ + pkg-config \ + sudo \ + swiftlang \ + unzip \ + wget && \ + update-ca-certificates -f + +RUN useradd -m builder && passwd -d builder +RUN echo "builder ALL=(ALL) ALL" >> /etc/sudoers +WORKDIR /home/builder +USER builder + +RUN curl -fsSL https://bun.sh/install | bash +RUN \ + echo "export BUN_INSTALL=\"\$HOME/.bun\"" >> $HOME/.profile && \ + echo "export PATH=\"\$BUN_INSTALL/bin:\$PATH\"" >> $HOME/.profile + +USER root +WORKDIR / +CMD ["bash", "-l"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 00000000..4ad86142 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,139 @@ +# Docker + +## Using docker-compose + +You may build your changes by using the compose file. First create an `.env` +file in /docker. The contents should be similar to: + +```text +HOSTUID=1000 +HOSTGID=1000 +IMAGE="ghcr.io/KaruroChori/vs-fltk:build-env" +ENTRYPOINT:$PWD/docker/default-entry.sh +SOURCE_ROOT=$PWD +``` + +Replace the values for HOSTUID and HOSTGID with your system uid and gid. Then, +from the source root: + + docker-compose -f docker/docker-compose.yml run --rm dev + +This will start the container and build the app. + +To enter the build environment without actually building the app: + + export ENTRYPOINT=$PWD/docker/shell-entry.sh + docker-compose -f docker/docker-compose.yml run --rm dev + +Remember to unset ENTRYPOINT when you wish to use the default again. + + + +All of the above methods will mount your current directory as */workspace* +inside the container. Your username will be *builder*. By default, you will +not have root privileges (which are not necessary to build and test). However, +you can use `sudo` if you need to run `apt` or any other commands that require +root access. + +## Notes + +In the examples above, we've included `--rm` as an argument. This normally +removes the container after it's exited. `docker ps -a` displays containers +that still exist so you may periodically want to make sure you don't have +unused or unwanted containers. See the official [Docker docs] for more +information about working with containers. You may, for example, want to +"reuse" a container, in which case, simply omit the `--rm`. + +## Getting the image + +You can pull the image manually: + + docker pull ghcr.io/KaruroChori/vs-fltk:build-env + +If you use `docker-compose` or `docker run ...` the image will be pulled +automatically the first time. + +## Running the app from the container + +Note the following instructions were adapted from instructions generated by +ChatGPT. The X11 instructions were tested on Manjaro Linux. Use at your own +risk. Please update these docs if you have any information about accuracy or +security-related considerations. + +To run an application from a Docker container that requires access to the host +machine's graphics (such as a GUI application), you'll need to share certain +resources from the host with the container. This involves passing through the +host's display (X11 or Wayland, depending on your system) and sharing the +necessary devices. Here's a general guide: + +### For X11-based systems (e.g., most Linux desktop environments) + +1. **Install dependencies on the host:** + Make sure you have `xhost` installed, which allows you to control access to + the X server. + + sudo apt install x11-xserver-utils # For Ubuntu/Debian + sudo pacman -S xorg-xhost # For Arch-based + + +2. **Allow access to X server:** + Before running the container, allow Docker to access your X server: + + xhost +local:docker + + +3. **Run the container with access to the display:** + When starting the container, pass the display environment variable + (`$DISPLAY`) and mount the X11 socket. Instead of *dev" for the last + argument of `docker-compose` (see above), use *xgui*, which essentially + adds these three arguments (through the compose configuration): + +```sh + --env="DISPLAY" \ + --env="QT_X11_NO_MITSHM=1" \ + --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" +``` + + - `--env="DISPLAY"`: Passes the display from the host to the container. + - `--env="QT_X11_NO_MITSHM=1"`: Some applications may need this to avoid shared memory issues. + - `--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw"`: Shares the X11 socket. + +4. **Run the graphical application inside the container:** + Once inside the container, running the app should open its GUI on your host's screen. + +### For Wayland-based systems (e.g., some modern Linux environments): + +1. **Share the Wayland display:** + If your system uses Wayland, you need to pass the Wayland display and devices: + +```sh + --env="WAYLAND_DISPLAY=$WAYLAND_DISPLAY" \ + --volume="/run/user/$(id -u)/wayland:/run/user/$(id -u)/wayland" \ + --device=/dev/dri \ +``` + + - `--env="WAYLAND_DISPLAY=$WAYLAND_DISPLAY"`: Passes the Wayland display variable. + - `--volume="/run/user/$(id -u)/wayland:/run/user/$(id -u)/wayland"`: Shares the Wayland display socket. + - `--device=/dev/dri`: Provides access to GPU devices (for rendering). + +### Additional considerations: + +- **GPU access**: If your application requires GPU acceleration (e.g., +OpenGL), you may also need to pass through GPU devices to the container. For +example, with NVIDIA, you can use the NVIDIA Docker runtime: + + --gpus all -it + +- **X11 access security**: Allowing Docker to connect to your X server with `xhost +local:docker` is not secure. After you're done, revoke access: + + xhost -local:docker diff --git a/docker/default-entry.sh b/docker/default-entry.sh new file mode 100755 index 00000000..c241bad6 --- /dev/null +++ b/docker/default-entry.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e +/docker/main_entry.sh + +su builder -c "bash -l -c '\ + cd /workspace && \ + bun install && + bun run codegen && + bun run meson-setup.clang-release && + meson compile -C build/ vs:executable + '" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000..345a3912 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,37 @@ +services: + dev: + image: $IMAGE + container_name: vs-fltk-env + entrypoint: $ENTRYPOINT + volumes: + - $SOURCE_ROOT:/workspace + - $ENTRYPOINT:$ENTRYPOINT + - ${PWD}/docker/main_entry.sh:/docker/main_entry.sh + environment: + HOSTUID: $HOSTUID + HOSTGID: $HOSTGID + ENTRYPOINT: $ENTRYPOINT + working_dir: /workspace + stdin_open: true # Allows interactive mode + tty: true # Allocate a pseudo-TTY + restart: "no" + + xgui: + image: $IMAGE + container_name: vs-fltk-gui + entrypoint: $ENTRYPOINT + volumes: + - $SOURCE_ROOT:/workspace + - $ENTRYPOINT:$ENTRYPOINT + - ${PWD}/docker/main_entry.sh:/docker/main_entry.sh + - /tmp/.X11-unix:/tmp/.X11-unix:rw + environment: + HOSTUID: $HOSTUID + HOSTGID: $HOSTGID + ENTRYPOINT: $ENTRYPOINT + DISPLAY: $DISPLAY + QT_X11_NO_MITSHM: 1 + working_dir: /workspace + stdin_open: true # Allows interactive mode + tty: true # Allocate a pseudo-TTY + restart: "no" diff --git a/docker/main_entry.sh b/docker/main_entry.sh new file mode 100755 index 00000000..b4e773eb --- /dev/null +++ b/docker/main_entry.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# main_entry.sh + +set -e + +OLDPWD=$PWD + +if [ -z "$HOSTUID" ]; then + echo "HOSTUID is not set." + exit 1 +fi + +if [ -z "$HOSTGID" ]; then + echo "HOSTGID is not set." + exit 1 +fi + +usermod -u $HOSTUID builder +groupmod -g $HOSTGID builder +chown -R $HOSTUID:$HOSTGID /home/builder diff --git a/docker/shell-entry.sh b/docker/shell-entry.sh new file mode 100755 index 00000000..b38010b2 --- /dev/null +++ b/docker/shell-entry.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +/docker/main_entry.sh + +su builder -l -c "cd /workspace && bash"