Add Docker images for linux arm64, armv7, 386 (#697)

* Add multi-platform Docker support for ARM64, ARMv7, and 386

* Support freebsd amd64 for server

* Build docker images locally
This commit is contained in:
Sung 2025-10-19 14:30:55 -07:00 committed by GitHub
commit 7d44c541a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 122 additions and 180 deletions

View file

@ -55,10 +55,19 @@ jobs:
./scripts/generate-changelog.sh server "$TAG" "$PREV_TAG" > /tmp/changelog.txt
cat /tmp/changelog.txt
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Prepare Docker build context
run: |
VERSION="${{ steps.version.outputs.version }}"
cp build/server/dnote_server_${VERSION}_linux_amd64.tar.gz host/docker/
cp build/server/dnote_server_${VERSION}_linux_arm64.tar.gz host/docker/
cp build/server/dnote_server_${VERSION}_linux_arm.tar.gz host/docker/
cp build/server/dnote_server_${VERSION}_linux_386.tar.gz host/docker/
- name: Login to Docker Hub
uses: docker/login-action@v3
@ -71,11 +80,12 @@ jobs:
with:
context: ./host/docker
push: true
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386
tags: |
dnote/dnote:${{ steps.version.outputs.version }}
dnote/dnote:latest
build-args: |
tarballName=dnote_server_${{ steps.version.outputs.version }}_linux_amd64.tar.gz
version=${{ steps.version.outputs.version }}
- name: Create GitHub release
env:

View file

@ -67,6 +67,15 @@ endif
@${currentDir}/scripts/server/build.sh $(version)
.PHONY: build-server
build-server-docker: build-server
ifndef version
$(error version is required. Usage: make version=0.1.0 [platform=linux/amd64] build-server-docker)
endif
@echo "==> building Docker image"
@(cd ${currentDir}/host/docker && ./build.sh $(version) $(platform))
.PHONY: build-server-docker
build-cli:
ifeq ($(debug), true)
@echo "==> building cli in dev mode"
@ -82,53 +91,6 @@ endif
endif
.PHONY: build-cli
## release
release-cli: clean build-cli
ifndef version
$(error version is required. Usage: make version=0.1.0 release-cli)
endif
ifndef GH
$(error please install github-cli)
endif
@echo "==> releasing cli"
@${currentDir}/scripts/release.sh cli $(version) ${cliOutputDir}
.PHONY: release-cli
release-cli-homebrew:
ifndef version
$(error version is required. Usage: make version=0.1.0 release-cli-homebrew)
endif
@echo "==> releasing cli on Homebrew"
@${currentDir}/scripts/cli/release-homebrew.sh $(version)
.PHONY: release-cli
release-server:
ifndef version
$(error version is required. Usage: make version=0.1.0 release-server)
endif
ifndef GH
$(error please install github-cli)
endif
@echo "==> releasing server"
@${currentDir}/scripts/release.sh server $(version) ${serverOutputDir}
@echo "==> building and releasing docker image"
@(cd ${currentDir}/host/docker && ./build.sh $(version))
@(cd ${currentDir}/host/docker && ./release.sh $(version))
.PHONY: release-server
# migrations
create-migration:
ifndef filename
$(error filename is required. Usage: make filename=your-filename create-migration)
endif
@(cd ${currentDir}/pkg/server/database && ./scripts/create-migration.sh $(filename))
.PHONY: create-migration
clean:
@git clean -f
@rm -rf build

View file

@ -1,12 +1,30 @@
FROM busybox:glibc
ARG tarballName
RUN test -n "$tarballName"
ARG TARGETPLATFORM
ARG version
WORKDIR dnote
RUN test -n "$TARGETPLATFORM" || (echo "TARGETPLATFORM is required" && exit 1)
RUN test -n "$version" || (echo "version is required" && exit 1)
COPY "$tarballName" .
RUN tar -xvzf "$tarballName"
WORKDIR /tmp/tarballs
# Copy all architecture tarballs
COPY dnote_server_*.tar.gz ./
# Select and extract the correct tarball based on target platform
RUN case "$TARGETPLATFORM" in \
"linux/amd64") ARCH="amd64" ;; \
"linux/arm64") ARCH="arm64" ;; \
"linux/arm/v7") ARCH="arm" ;; \
"linux/386") ARCH="386" ;; \
*) echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \
esac && \
TARBALL="dnote_server_${version}_linux_${ARCH}.tar.gz" && \
echo "Extracting $TARBALL for $TARGETPLATFORM" && \
mkdir -p /dnote && \
tar -xvzf "$TARBALL" -C /dnote
WORKDIR /dnote
COPY entrypoint.sh .
ENTRYPOINT ["./entrypoint.sh"]

View file

@ -1,13 +1,85 @@
#!/usr/bin/env bash
# Build Docker image for local testing
#
# Usage:
# # builds for host platform (auto-detected)
# ./build.sh 1.0.0
#
# # builds arm64
# ./build.sh 1.0.0 linux/arm64
#
# # builds multiple platforms
# ./build.sh 1.0.0 "linux/amd64,linux/arm64,linux/arm/v7,linux/386"
set -eux
version=$1
# Detect host platform if not specified
if [ -z "${2:-}" ]; then
HOST_ARCH=$(uname -m)
case "$HOST_ARCH" in
x86_64) platform="linux/amd64" ;;
aarch64|arm64) platform="linux/arm64" ;;
armv7l) platform="linux/arm/v7" ;;
i386|i686) platform="linux/386" ;;
*)
echo "Warning: Unsupported architecture: $HOST_ARCH, defaulting to linux/amd64"
platform="linux/amd64"
;;
esac
echo "Auto-detected platform: $platform"
else
platform=$2
fi
dir=$(dirname "${BASH_SOURCE[0]}")
projectDir="$dir/../.."
tarballName="dnote_server_${version}_linux_amd64.tar.gz"
# copy over the build artifact to the Docker build context
cp "$projectDir/build/server/$tarballName" "$dir"
# Copy all Linux tarballs to Docker build context
cp "$projectDir/build/server/dnote_server_${version}_linux_amd64.tar.gz" "$dir/"
cp "$projectDir/build/server/dnote_server_${version}_linux_arm64.tar.gz" "$dir/"
cp "$projectDir/build/server/dnote_server_${version}_linux_arm.tar.gz" "$dir/"
cp "$projectDir/build/server/dnote_server_${version}_linux_386.tar.gz" "$dir/"
docker build --network=host -t dnote/dnote:"$version" --build-arg tarballName="$tarballName" .
# Count platforms (check for comma)
if [[ "$platform" == *","* ]]; then
echo "Building for multiple platforms: $platform"
# Check if multiarch builder exists, create if not
if ! docker buildx ls | grep -q "multiarch"; then
echo "Creating multiarch builder for multi-platform builds..."
docker buildx create --name multiarch --use
docker buildx inspect --bootstrap
else
echo "Using existing multiarch builder"
docker buildx use multiarch
fi
echo ""
docker buildx build \
--platform "$platform" \
-t dnote/dnote:"$version" \
-t dnote/dnote:latest \
--build-arg version="$version" \
"$dir"
# Switch back to default builder
docker buildx use default
else
echo "Building for single platform: $platform"
echo "Image will be loaded to local Docker daemon"
docker buildx build \
--platform "$platform" \
-t dnote/dnote:"$version" \
-t dnote/dnote:latest \
--build-arg version="$version" \
--load \
"$dir"
fi
echo ""
echo "Build complete!"
if [[ "$platform" != *","* ]]; then
echo "Test with: docker run --rm dnote/dnote:$version ./dnote-server version"
fi

View file

@ -1,13 +0,0 @@
#!/usr/bin/env bash
set -eux
version=$1
docker login
# tag the release
docker tag dnote/dnote:"$version" dnote/dnote:latest
# publish
docker push dnote/dnote:"$version"
docker push dnote/dnote:latest

View file

@ -1,53 +0,0 @@
#!/usr/bin/env bash
set -eux
currentDir=$(dirname "${BASH_SOURCE[0]}")
cliHomebrewDir=${currentDir}/../../homebrew-dnote
if [ ! -d "$cliHomebrewDir" ]; then
echo "homebrew-dnote not found locally. Cloning."
git clone git@github.com:dnote/homebrew-dnote.git "$cliHomebrewDir"
fi
version=$1
echo "version: $version"
# Download source tarball and calculate SHA256
source_url="https://github.com/dnote/dnote/archive/refs/tags/cli-v${version}.tar.gz"
echo "Calculating SHA256 for: $source_url"
sha=$(curl -L "$source_url" | shasum -a 256 | cut -d ' ' -f 1)
pushd "$cliHomebrewDir"
echo "pulling latest dnote-homebrew repo"
git checkout master
git pull origin master
cat > ./Formula/dnote.rb << EOF
class Dnote < Formula
desc "Simple command line notebook for programmers"
homepage "https://www.getdnote.com"
url "https://github.com/dnote/dnote/archive/refs/tags/cli-v${version}.tar.gz"
sha256 "${sha}"
license "GPL-3.0"
head "https://github.com/dnote/dnote.git", branch: "master"
depends_on "go" => :build
def install
ldflags = "-s -w -X main.apiEndpoint=https://api.getdnote.com -X main.versionTag=#{version}"
system "go", "build", *std_go_args(ldflags: ldflags), "-tags", "fts5", "./pkg/cli"
end
test do
system "#{bin}/dnote", "version"
end
end
EOF
git add .
git commit --author="Bot <bot@getdnote.com>" -m "Release ${version}"
git push origin master
popd

View file

@ -1,57 +0,0 @@
#!/usr/bin/env bash
#
# release.sh releases the tarballs and checksum in the build directory
# to GitHub and brew. A prerequisite is to build those files using build.sh.
# use: ./scripts/release.sh cli v0.4.8 path/to/assets
set -euxo pipefail
project=$1
version=$2
assetPath=$3
if [ "$project" != "cli" ] && [ "$project" != "server" ]; then
echo "unrecognized project '$project'"
exit 1
fi
if [ -z "$version" ]; then
echo "no version specified."
exit 1
fi
if [[ $version == v* ]]; then
echo "do not prefix version with v"
exit 1
fi
# 1. push tag
version_tag="$project-v$version"
echo "* tagging and pushing the tag"
git tag -a "$version_tag" -m "Release $version_tag"
git push --tags
# 2. release on GitHub
files=("$assetPath"/*)
file_flags=()
for file in "${files[@]}"; do
file_flags+=("$file")
done
# mark as prerelease if version is not in a form of major.minor.patch
# e.g. 1.0.1-beta.1
flags=()
if [[ ! "$version" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then
flags+=("--prerelease")
fi
echo "* creating release"
set -x
# Create release
gh release create \
"$version_tag" \
"${file_flags[@]}" \
"${flags[@]}" \
--title="$version_tag"\
--notes="Please see the [CHANGELOG](https://github.com/dnote/dnote/blob/master/CHANGELOG.md)" \
--draft

View file

@ -74,3 +74,6 @@ go install src.techknowlogick.com/xgo@latest
build linux amd64
build linux arm64
build linux arm
build linux 386
build freebsd amd64