diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 09425a08..c043439c 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -20,155 +20,31 @@ on:
 # Steps to run for the Workflow
 jobs:
   build:
-
-    # Run these steps on Ubuntu
     runs-on: ubuntu-latest
-
+    container:
+      image: jf002/infinitime-build
     steps:
-
-      #########################################################################################
-      # Download and Cache Dependencies
-
-      - name: Install cmake
-        uses: lukka/get-cmake@v3.18.3
-
-      - name: Check cache for Embedded Arm Toolchain arm-none-eabi-gcc
-        id:   cache-toolchain
-        uses: actions/cache@v2
-        env:
-          cache-name: cache-toolchain-9-2020-q2
-        with:
-          path: ${{ runner.temp }}/arm-none-eabi
-          key:  ${{ runner.os }}-build-${{ env.cache-name }}
-          restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}
-
-      - name: Install Embedded Arm Toolchain arm-none-eabi-gcc
-        if:   steps.cache-toolchain.outputs.cache-hit != 'true'  # Install toolchain if not found in cache
-        uses: fiam/arm-none-eabi-gcc@v1.0.4
-        with:
-          # GNU Embedded Toolchain for Arm release name, in the V-YYYY-qZ format (e.g. "9-2019-q4")
-          release: 9-2020-q2
-          # Directory to unpack GCC to. Defaults to a temporary directory.
-          directory: ${{ runner.temp }}/arm-none-eabi
-
-      - name: Check cache for nRF5 SDK
-        id:   cache-nrf5sdk
-        uses: actions/cache@v2
-        env:
-          cache-name: cache-nrf5sdk
-        with:
-          path: ${{ runner.temp }}/nrf5_sdk
-          key:  ${{ runner.os }}-build-${{ env.cache-name }}
-          restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}
-
-      - name: Install nRF5 SDK
-        if:   steps.cache-nrf5sdk.outputs.cache-hit != 'true'  # Install SDK if not found in cache
-        run:  |
-          cd ${{ runner.temp }}
-          curl https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip -o nrf5_sdk.zip
-          unzip nrf5_sdk.zip
-          mv nRF5_SDK_15.3.0_59ac345 nrf5_sdk
-
-      - name: Check cache for MCUBoot
-        id:   cache-mcuboot
-        uses: actions/cache@v2
-        env:
-          cache-name: cache-mcuboot
-        with:
-          path: ${{ runner.temp }}/mcuboot
-          key:  ${{ runner.os }}-build-${{ env.cache-name }}
-          restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}
-
-      - name: Install MCUBoot
-        if:   steps.cache-mcuboot.outputs.cache-hit != 'true'  # Install MCUBoot if not found in cache
-        run:  |
-          cd ${{ runner.temp }}
-          git clone --branch v1.7.2 https://github.com/mcu-tools/mcuboot
-
-      - name: Install imgtool dependencies
-        run:  |
-          pip3 install --user -r ${{ runner.temp }}/mcuboot/scripts/requirements.txt
-
-      - name: Install adafruit-nrfutil
-        run:  |
-          pip3 install --user wheel
-          pip3 install --user setuptools
-          pip3 install --user adafruit-nrfutil
-
-      - name: Install lv_font_conv
-        run:
-          npm i -g lv_font_conv@1.5.2
-
-        #########################################################################################
-        # Checkout
-
+      - name: Workaround permission issues
+        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
       - name: Checkout source files
         uses: actions/checkout@v2
         with:
           submodules: recursive
-
-      - name: Show files
-        run:  set ; pwd ; ls -l
-
-      #########################################################################################
-      # CMake
-
-      - name: CMake
-        run:  |
-          mkdir -p build
-          cd build
-          cmake -G Ninja -DARM_NONE_EABI_TOOLCHAIN_PATH=${{ runner.temp }}/arm-none-eabi -DNRF5_SDK_PATH=${{ runner.temp }}/nrf5_sdk -DUSE_OPENOCD=1 -DBUILD_DFU=1 ../
-
-        #########################################################################################
-        # Make and Upload DFU Package
-        # pinetime-mcuboot-app.img must be flashed at address 0x8000 in the internal flash memory with OpenOCD:
-        # program image.bin 0x8000
-
-        # For Debugging Builds: Remove "make" option "-j" for clearer output. Add "--trace" to see details.
-        # For Faster Builds: Add "make" option "-j"
-
-      - name: Make pinetime-mcuboot-app
-        run:  |
-          cmake --build build --target pinetime-mcuboot-app
-
-      - name: Unzip DFU package
-        run:  |
-          # Unzip the package because Upload Artifact will zip up the files
-          unzip build/src/pinetime-mcuboot-app-dfu*.zip -d build/src/pinetime-mcuboot-app-dfu
-
-      - name: Upload DFU package
+      - name: Build
+        shell: bash
+        env:
+          SOURCES_DIR: .
+        run: |
+          /opt/build.sh all
+      - name: Upload DFU artifacts
         uses: actions/upload-artifact@v2
         with:
-          name: pinetime-mcuboot-app-dfu
-          path: build/src/pinetime-mcuboot-app-dfu/*
-
-        #########################################################################################
-        # Make and Upload Standalone Firmware
-
-      - name: Make pinetime-app
-        run:  |
-          cmake --build build --target pinetime-app
-
-      - name: Upload standalone firmware
+          name: InfiniTime DFU file
+          path: |
+            ./build/output/pinetime-mcuboot-app-dfu-*.zip
+      - name: Upload MCUBoot image artifacts
         uses: actions/upload-artifact@v2
         with:
-          name: pinetime-app.out
-          path: build/src/pinetime-app*.out
-
-        #########################################################################################
-        # Make but don't Upload the Recovery Firmware to be sure it builds correctly
-
-      - name: Make pinetime-recovery
-        run:  |
-          cmake --build build --target pinetime-recovery
-
-      #########################################################################################
-      # Finish
-
-      - name: Find output
-        run:  |
-          find . -name "pinetime-app.*" -ls
-          find . -name "pinetime-mcuboot-app.*" -ls
-
-# Embedded Arm Toolchain and nRF5 SDK will only be cached if the build succeeds.
-# So make sure that the first build always succeeds, e.g. comment out the "Make" step.
+          name: InfiniTime MCUBoot image file
+          path: |
+            ./build/output/pinetime-mcuboot-app-image-*.bin
diff --git a/doc/buildWithDocker.md b/doc/buildWithDocker.md
index a57893c9..cfd054fb 100644
--- a/doc/buildWithDocker.md
+++ b/doc/buildWithDocker.md
@@ -44,19 +44,19 @@ docker run --rm -it -v $(pwd):/sources --user 1234:1234 infinitime-build
 
 ## Using the image from Docker Hub
 
-The image is available via Docker Hub for both the amd64 and arm64v8 architectures at [pfeerick/infinitime-build](https://hub.docker.com/r/pfeerick/infinitime-build).
+The image is available via Docker Hub for both the amd64 and arm64v8 architectures at [jf002/infinitime-build](https://hub.docker.com/repository/docker/jf002/infinitime-build).
 
 It can be pulled (downloaded) using the following command:
 
 ```bash
-docker pull pfeerick/infinitime-build
+docker pull jf002/infinitime-build
 ```
 
 The default `latest` tag *should* automatically identify the correct image architecture, but if for some reason Docker does not, you can specify it manually:
 
-* For AMD64 (x86_64) systems: `docker pull pfeerick/infinitime-build:amd64`
+* For AMD64 (x86_64) systems: `docker pull jf002/infinitime-build:amd64`
 
-* For ARM64v8 (ARM64/aarch64) systems: `docker pull pfeerick/infinitime-build:arm64v8`
+* For ARM64v8 (ARM64/aarch64) systems: `docker pull jf002/infinitime-build:arm64v8`
 
 ## Build the image
 
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 10bed55f..f2d187d0 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -44,10 +44,5 @@ RUN bash -c "source /opt/build.sh; GetNrfSdk;"
 # McuBoot
 RUN bash -c "source /opt/build.sh; GetMcuBoot;"
 
-ARG PUID=1000
-ARG PGID=1000
-RUN groupadd --system --gid $PGID infinitime && useradd --system --uid $PUID --gid $PGID infinitime
-
-USER infinitime:infinitime
 ENV SOURCES_DIR /sources
 CMD ["/opt/build.sh"]
diff --git a/docker/build.sh b/docker/build.sh
index d86e7c21..878d9ec6 100755
--- a/docker/build.sh
+++ b/docker/build.sh
@@ -9,7 +9,7 @@ set -e
 export TOOLS_DIR="${TOOLS_DIR:=/opt}"
 export SOURCES_DIR="${SOURCES_DIR:=/sources}"
 export BUILD_DIR="${BUILD_DIR:=$SOURCES_DIR/build}"
-export OUTPUT_DIR="${OUTPUT_DIR:=$BUILD_DIR/output}"
+export OUTPUT_DIR="${OUTPUT_DIR:=$SOURCES_DIR/build/output}"
 
 export BUILD_TYPE=${BUILD_TYPE:=Release}
 export GCC_ARM_VER=${GCC_ARM_VER:="gcc-arm-none-eabi-9-2020-q2-update"}
@@ -22,7 +22,7 @@ main() {
   local target="$1"
 
   mkdir -p "$TOOLS_DIR"
-  
+
   [[ ! -d "$TOOLS_DIR/$GCC_ARM_VER" ]] && GetGcc
   [[ ! -d "$TOOLS_DIR/$NRF_SDK_VER" ]] && GetNrfSdk
   [[ ! -d "$TOOLS_DIR/mcuboot" ]] && GetMcuBoot
@@ -31,7 +31,7 @@ main() {
 
   CmakeGenerate
   CmakeBuild $target
-  BUILD_RESULT=$? 
+  BUILD_RESULT=$?
   if [ "$DISABLE_POSTBUILD" != "true" -a "$BUILD_RESULT" == 0 ]; then
     source "$BUILD_DIR/post_build.sh"
   fi
@@ -54,18 +54,14 @@ GetNrfSdk() {
 }
 
 CmakeGenerate() {
-  # We can swap the CD and trailing SOURCES_DIR for -B and -S respectively
-  # once we go to newer CMake (Ubuntu 18.10 gives us CMake 3.10)
-  cd "$BUILD_DIR"
-
   cmake -G "Unix Makefiles" \
+    -S "$SOURCES_DIR" \
+    -B "$BUILD_DIR" \
     -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
     -DUSE_OPENOCD=1 \
     -DARM_NONE_EABI_TOOLCHAIN_PATH="$TOOLS_DIR/$GCC_ARM_VER" \
     -DNRF5_SDK_PATH="$TOOLS_DIR/$NRF_SDK_VER" \
-    -DBUILD_DFU=1 \
-    "$SOURCES_DIR"
-  cmake -L -N .
+    -DBUILD_DFU=1
 }
 
 CmakeBuild() {
diff --git a/docker/post_build.sh.in b/docker/post_build.sh.in
index db6e7a94..8c94471a 100755
--- a/docker/post_build.sh.in
+++ b/docker/post_build.sh.in
@@ -15,12 +15,10 @@ cp "$BUILD_DIR/src/pinetime-mcuboot-app-dfu-$PROJECT_VERSION.zip" "$OUTPUT_DIR/p
 cp "$BUILD_DIR/src/pinetime-mcuboot-recovery-loader-image-$PROJECT_VERSION.bin" "$OUTPUT_DIR/pinetime-mcuboot-recovery-loader-image-$PROJECT_VERSION.bin"
 cp "$BUILD_DIR/src/pinetime-mcuboot-recovery-loader-dfu-$PROJECT_VERSION.zip" "$OUTPUT_DIR/pinetime-mcuboot-recovery-loader-dfu-$PROJECT_VERSION.zip"
 
-
 mkdir -p "$OUTPUT_DIR/src"
-cd "$BUILD_DIR"
-cp src/*.bin "$OUTPUT_DIR/src"
-cp src/*.hex "$OUTPUT_DIR/src"
-cp src/*.out "$OUTPUT_DIR/src"
-cp src/*.map "$OUTPUT_DIR/src"
+cp $BUILD_DIR/src/*.bin "$OUTPUT_DIR/src/"
+cp $BUILD_DIR/src/*.hex "$OUTPUT_DIR/src/"
+cp $BUILD_DIR/src/*.out "$OUTPUT_DIR/src/"
+cp $BUILD_DIR/src/*.map "$OUTPUT_DIR/src/"
 
 ls -RUv1 "$OUTPUT_DIR" | sed 's;^\([^/]\); \1;g'
\ No newline at end of file