mirror of https://github.com/coder/coder.git
feat: add git to Docker image (#6034)
This commit is contained in:
parent
a655f03a1e
commit
b45c445255
|
@ -0,0 +1,53 @@
|
||||||
|
name: docker-base
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- Dockerfile.base
|
||||||
|
- Dockerfile
|
||||||
|
|
||||||
|
schedule:
|
||||||
|
# Run every week at 09:43 on Monday, Wednesday and Friday. We build this
|
||||||
|
# frequently to ensure that packages are up-to-date.
|
||||||
|
- cron: "43 9 * * 1,3,5"
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Avoid running multiple jobs for the same commit.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-docker-base
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.repository_owner == 'coder'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Docker login
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Create empty base-build-context directory
|
||||||
|
run: mkdir base-build-context
|
||||||
|
|
||||||
|
- name: Install depot.dev CLI
|
||||||
|
uses: depot/setup-action@v1
|
||||||
|
|
||||||
|
# This uses OIDC authentication, so no auth variables are required.
|
||||||
|
- name: Build base Docker image via depot.dev
|
||||||
|
uses: depot/build-push-action@v1
|
||||||
|
with:
|
||||||
|
project: wl5hnrrkns
|
||||||
|
context: base-build-context
|
||||||
|
file: Dockerfile.base
|
||||||
|
pull: true
|
||||||
|
no-cache: true
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
ghcr.io/coder/coder-base:latest
|
|
@ -112,17 +112,17 @@ jobs:
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
wget -O /tmp/nfpm.deb https://github.com/goreleaser/nfpm/releases/download/v2.18.1/nfpm_amd64.deb
|
wget -O /tmp/nfpm.deb https://github.com/goreleaser/nfpm/releases/download/v2.18.1/nfpm_amd64.deb
|
||||||
sudo dpkg -i /tmp/nfpm.deb
|
sudo dpkg -i /tmp/nfpm.deb
|
||||||
|
rm /tmp/nfpm.deb
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
wget -O /tmp/rcodesign.tar.gz https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-x86_64-unknown-linux-musl.tar.gz
|
||||||
# Install a prebuilt binary of rcodesign for linux amd64. Once the
|
sudo tar -xzf /tmp/rcodesign.tar.gz \
|
||||||
# following PR is merged and released upstream, we can download
|
-C /usr/bin \
|
||||||
# directly from GitHub releases instead:
|
--strip-components=1 \
|
||||||
# https://github.com/indygreg/PyOxidizer/pull/635
|
apple-codesign-0.22.0-x86_64-unknown-linux-musl/rcodesign
|
||||||
wget -O /tmp/rcodesign https://cdn.discordapp.com/attachments/283356472258199552/1016767245717872700/rcodesign
|
rm /tmp/rcodesign.tar.gz
|
||||||
sudo install --mode 755 /tmp/rcodesign /usr/local/bin/rcodesign
|
|
||||||
|
|
||||||
- name: Setup Apple Developer certificate and API key
|
- name: Setup Apple Developer certificate and API key
|
||||||
run: |
|
run: |
|
||||||
|
@ -160,6 +160,39 @@ jobs:
|
||||||
- name: Delete Apple Developer certificate and API key
|
- name: Delete Apple Developer certificate and API key
|
||||||
run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
|
||||||
|
|
||||||
|
- name: Determine base image tag
|
||||||
|
id: image-base-tag
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ "${CODER_RELEASE:-}" != *t* ]] || [[ "${CODER_DRY_RUN:-}" == *t* ]]; then
|
||||||
|
# Empty value means use the default and avoid building a fresh one.
|
||||||
|
echo "tag=" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "tag=$(CODER_IMAGE_BASE=ghcr.io/coder/coder-base ./scripts/image_tag.sh)" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Create empty base-build-context directory
|
||||||
|
if: steps.image-base-tag.outputs.tag != ''
|
||||||
|
run: mkdir base-build-context
|
||||||
|
|
||||||
|
- name: Install depot.dev CLI
|
||||||
|
if: steps.image-base-tag.outputs.tag != ''
|
||||||
|
uses: depot/setup-action@v1
|
||||||
|
|
||||||
|
# This uses OIDC authentication, so no auth variables are required.
|
||||||
|
- name: Build base Docker image via depot.dev
|
||||||
|
if: steps.image-base-tag.outputs.tag != ''
|
||||||
|
uses: depot/build-push-action@v1
|
||||||
|
with:
|
||||||
|
project: wl5hnrrkns
|
||||||
|
context: base-build-context
|
||||||
|
file: Dockerfile.base
|
||||||
|
pull: true
|
||||||
|
no-cache: true
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ steps.image-base-tag.outputs.tag }}
|
||||||
|
|
||||||
- name: Build Linux Docker images
|
- name: Build Linux Docker images
|
||||||
run: |
|
run: |
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
@ -188,6 +221,8 @@ jobs:
|
||||||
--target "$(./scripts/image_tag.sh --version latest)" \
|
--target "$(./scripts/image_tag.sh --version latest)" \
|
||||||
$(cat build/coder_"$version"_linux_{amd64,arm64,armv7}.tag)
|
$(cat build/coder_"$version"_linux_{amd64,arm64,armv7}.tag)
|
||||||
fi
|
fi
|
||||||
|
env:
|
||||||
|
CODER_BASE_IMAGE_TAG: ${{ steps.image-base-tag.outputs.tag }}
|
||||||
|
|
||||||
- name: ls build
|
- name: ls build
|
||||||
run: ls -lh build
|
run: ls -lh build
|
||||||
|
@ -252,6 +287,14 @@ jobs:
|
||||||
./build/*.rpm
|
./build/*.rpm
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
|
- name: Start Packer builds
|
||||||
|
uses: peter-evans/repository-dispatch@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CDRCI_GITHUB_TOKEN }}
|
||||||
|
repository: coder/packages
|
||||||
|
event-type: coder-release
|
||||||
|
client-payload: '{"coder_version": "${{ steps.version.outputs.version }}"}'
|
||||||
|
|
||||||
publish-winget:
|
publish-winget:
|
||||||
name: Publish to winget-pkgs
|
name: Publish to winget-pkgs
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
@ -333,11 +376,3 @@ jobs:
|
||||||
# For gh CLI. We need a real token since we're commenting on a PR in a
|
# For gh CLI. We need a real token since we're commenting on a PR in a
|
||||||
# different repo.
|
# different repo.
|
||||||
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Start Packer builds
|
|
||||||
uses: peter-evans/repository-dispatch@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.CDRCI_GITHUB_TOKEN }}
|
|
||||||
repository: coder/packages
|
|
||||||
event-type: coder-release
|
|
||||||
client-payload: '{"coder_version": "${{ needs.release.outputs.version }}"}'
|
|
||||||
|
|
|
@ -96,8 +96,20 @@ jobs:
|
||||||
id: build
|
id: build
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
image_job="build/coder_$(./scripts/version.sh)_linux_amd64.tag"
|
|
||||||
DOCKER_IMAGE_NO_PREREQUISITES=true make -j "$image_job"
|
version="$(./scripts/version.sh)"
|
||||||
|
image_job="build/coder_${version}_linux_amd64.tag"
|
||||||
|
|
||||||
|
# This environment variable force make to not build packages and
|
||||||
|
# archives (which the Docker image depends on due to technical reasons
|
||||||
|
# related to concurrent FS writes).
|
||||||
|
export DOCKER_IMAGE_NO_PREREQUISITES=true
|
||||||
|
# This environment variables forces scripts/build_docker.sh to build
|
||||||
|
# the base image tag locally instead of using the cached version from
|
||||||
|
# the registry.
|
||||||
|
export CODER_IMAGE_BUILD_BASE_TAG="$(CODER_IMAGE_BASE=coder-base ./scripts/image_tag.sh --version "$version")"
|
||||||
|
|
||||||
|
make -j "$image_job"
|
||||||
echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT
|
echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner
|
- name: Run Trivy vulnerability scanner
|
||||||
|
|
16
Dockerfile
16
Dockerfile
|
@ -2,7 +2,11 @@
|
||||||
# cross-compiled, it cannot have ANY "RUN" commands. All binaries are built
|
# cross-compiled, it cannot have ANY "RUN" commands. All binaries are built
|
||||||
# using the go toolchain on the host and then copied into the build context by
|
# using the go toolchain on the host and then copied into the build context by
|
||||||
# scripts/build_docker.sh.
|
# scripts/build_docker.sh.
|
||||||
FROM alpine:latest
|
#
|
||||||
|
# If you need RUN commands (e.g. to install tools via apk), add them to
|
||||||
|
# Dockerfile.base instead, which supports "RUN" commands.
|
||||||
|
ARG BASE_IMAGE
|
||||||
|
FROM $BASE_IMAGE
|
||||||
|
|
||||||
# LABEL doesn't add any real layers so it's fine (and easier) to do it here than
|
# LABEL doesn't add any real layers so it's fine (and easier) to do it here than
|
||||||
# in the build script.
|
# in the build script.
|
||||||
|
@ -14,17 +18,7 @@ LABEL \
|
||||||
org.opencontainers.image.source="https://github.com/coder/coder" \
|
org.opencontainers.image.source="https://github.com/coder/coder" \
|
||||||
org.opencontainers.image.version="$CODER_VERSION"
|
org.opencontainers.image.version="$CODER_VERSION"
|
||||||
|
|
||||||
# Create coder group and user. We cannot use `addgroup` and `adduser` because
|
|
||||||
# they won't work if we're building the image for a different architecture.
|
|
||||||
COPY --chown=0:0 --chmod=644 group passwd /etc/
|
|
||||||
COPY --chown=1000:1000 --chmod=700 empty-dir /home/coder
|
|
||||||
|
|
||||||
# The coder binary is injected by scripts/build_docker.sh.
|
# The coder binary is injected by scripts/build_docker.sh.
|
||||||
COPY --chown=1000:1000 --chmod=755 coder /opt/coder
|
COPY --chown=1000:1000 --chmod=755 coder /opt/coder
|
||||||
|
|
||||||
USER 1000:1000
|
|
||||||
ENV HOME=/home/coder
|
|
||||||
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt
|
|
||||||
WORKDIR /home/coder
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/opt/coder", "server" ]
|
ENTRYPOINT [ "/opt/coder", "server" ]
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# This is the base image used for Coder images. It's a multi-arch image that is
|
||||||
|
# built in depot.dev for all supported architectures. Since it's built on real
|
||||||
|
# hardware and not cross-compiled, it can have "RUN" commands.
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# We use a single RUN command to reduce the number of layers in the image.
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
bash \
|
||||||
|
git \
|
||||||
|
openssh-client && \
|
||||||
|
addgroup \
|
||||||
|
-g 1000 \
|
||||||
|
coder && \
|
||||||
|
adduser \
|
||||||
|
-D \
|
||||||
|
-s /bin/bash \
|
||||||
|
-h /home/coder \
|
||||||
|
-u 1000 \
|
||||||
|
-G coder \
|
||||||
|
coder
|
||||||
|
|
||||||
|
USER 1000:1000
|
||||||
|
ENV HOME=/home/coder
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt
|
||||||
|
WORKDIR /home/coder
|
|
@ -164,6 +164,12 @@ RUN apt-get update --quiet && apt-get install --yes \
|
||||||
# Configure FIPS-compliant policies
|
# Configure FIPS-compliant policies
|
||||||
update-crypto-policies --set FIPS
|
update-crypto-policies --set FIPS
|
||||||
|
|
||||||
|
# Install the docker buildx component.
|
||||||
|
RUN DOCKER_BUILDX_VERSION=$(curl -s "https://api.github.com/repos/docker/buildx/releases/latest" | grep '"tag_name":' | sed -E 's/.*"(v[^"]+)".*/\1/') && \
|
||||||
|
mkdir -p /usr/local/lib/docker/cli-plugins && \
|
||||||
|
curl -Lo /usr/local/lib/docker/cli-plugins/docker-buildx "https://github.com/docker/buildx/releases/download/${DOCKER_BUILDX_VERSION}/buildx-${DOCKER_BUILDX_VERSION}.linux-amd64" && \
|
||||||
|
chmod a+x /usr/local/lib/docker/cli-plugins/docker-buildx
|
||||||
|
|
||||||
# See https://github.com/cli/cli/issues/6175#issuecomment-1235984381 for proof
|
# See https://github.com/cli/cli/issues/6175#issuecomment-1235984381 for proof
|
||||||
# the apt repository is unreliable
|
# the apt repository is unreliable
|
||||||
RUN curl -L https://github.com/cli/cli/releases/download/v2.14.7/gh_2.14.7_linux_amd64.deb -o gh.deb && \
|
RUN curl -L https://github.com/cli/cli/releases/download/v2.14.7/gh_2.14.7_linux_amd64.deb -o gh.deb && \
|
||||||
|
|
|
@ -3,12 +3,19 @@
|
||||||
# This script builds a Docker image of Coder containing the given binary, for
|
# This script builds a Docker image of Coder containing the given binary, for
|
||||||
# the given architecture. Only linux binaries are supported at this time.
|
# the given architecture. Only linux binaries are supported at this time.
|
||||||
#
|
#
|
||||||
# Usage: ./build_docker.sh --arch amd64 [--version 1.2.3] [--target image_tag] [--push] path/to/coder
|
# Usage: ./build_docker.sh --arch amd64 [--version 1.2.3] [--target image_tag] [--build-base image_tag] [--push] path/to/coder
|
||||||
#
|
#
|
||||||
# The --arch parameter is required and accepts a Golang arch specification. It
|
# The --arch parameter is required and accepts a Golang arch specification. It
|
||||||
# will be automatically mapped to a suitable architecture that Docker accepts
|
# will be automatically mapped to a suitable architecture that Docker accepts
|
||||||
# before being passed to `docker buildx build`.
|
# before being passed to `docker buildx build`.
|
||||||
#
|
#
|
||||||
|
# The --build-base parameter is optional and specifies to build the base image
|
||||||
|
# in Dockerfile.base instead of pulling a copy from the registry. The string
|
||||||
|
# value is the tag to use for the built image (not pushed). This also consumes
|
||||||
|
# $CODER_IMAGE_BUILD_BASE_TAG for easily forcing a fresh build in CI.
|
||||||
|
#
|
||||||
|
# The default base image can be controlled via $CODER_BASE_IMAGE_TAG.
|
||||||
|
#
|
||||||
# The image will be built and tagged against the image tag returned by
|
# The image will be built and tagged against the image tag returned by
|
||||||
# ./image_tag.sh unless a --target parameter is supplied.
|
# ./image_tag.sh unless a --target parameter is supplied.
|
||||||
#
|
#
|
||||||
|
@ -22,12 +29,15 @@ set -euo pipefail
|
||||||
# shellcheck source=scripts/lib.sh
|
# shellcheck source=scripts/lib.sh
|
||||||
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
||||||
|
|
||||||
|
DEFAULT_BASE="${CODER_BASE_IMAGE_TAG:-ghcr.io/coder/coder-base:latest}"
|
||||||
|
|
||||||
arch=""
|
arch=""
|
||||||
image_tag=""
|
image_tag=""
|
||||||
|
build_base="${CODER_IMAGE_BUILD_BASE_TAG:-}"
|
||||||
version=""
|
version=""
|
||||||
push=0
|
push=0
|
||||||
|
|
||||||
args="$(getopt -o "" -l arch:,target:,version:,push -- "$@")"
|
args="$(getopt -o "" -l arch:,target:,build-base:,version:,push -- "$@")"
|
||||||
eval set -- "$args"
|
eval set -- "$args"
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
@ -43,6 +53,10 @@ while true; do
|
||||||
version="$2"
|
version="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--build-base)
|
||||||
|
build_base="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--push)
|
--push)
|
||||||
push=1
|
push=1
|
||||||
shift
|
shift
|
||||||
|
@ -98,31 +112,37 @@ fi
|
||||||
cdroot
|
cdroot
|
||||||
temp_dir="$(TMPDIR="$(dirname "$input_file")" mktemp -d)"
|
temp_dir="$(TMPDIR="$(dirname "$input_file")" mktemp -d)"
|
||||||
ln "$input_file" "$temp_dir/coder"
|
ln "$input_file" "$temp_dir/coder"
|
||||||
|
ln Dockerfile.base "$temp_dir/"
|
||||||
ln Dockerfile "$temp_dir/"
|
ln Dockerfile "$temp_dir/"
|
||||||
|
|
||||||
cd "$temp_dir"
|
cd "$temp_dir"
|
||||||
|
|
||||||
|
export DOCKER_BUILDKIT=1
|
||||||
|
|
||||||
|
base_image="$DEFAULT_BASE"
|
||||||
|
if [[ "$build_base" != "" ]]; then
|
||||||
|
log "--- Building base Docker image for $arch ($build_base)"
|
||||||
|
docker build \
|
||||||
|
--platform "$arch" \
|
||||||
|
--tag "$build_base" \
|
||||||
|
--no-cache \
|
||||||
|
-f Dockerfile.base \
|
||||||
|
. 1>&2
|
||||||
|
|
||||||
|
base_image="$build_base"
|
||||||
|
else
|
||||||
|
docker pull --platform "$arch" "$base_image" 1>&2
|
||||||
|
fi
|
||||||
|
|
||||||
log "--- Building Docker image for $arch ($image_tag)"
|
log "--- Building Docker image for $arch ($image_tag)"
|
||||||
|
|
||||||
# Pull the base image, copy the /etc/group and /etc/passwd files out of it, and
|
docker build \
|
||||||
# add the coder group and user. We have to do this in a separate step instead of
|
|
||||||
# using the RUN directive in the Dockerfile because you can't use RUN if you're
|
|
||||||
# building the image for a different architecture than the host.
|
|
||||||
docker pull --platform "$arch" alpine:latest 1>&2
|
|
||||||
|
|
||||||
temp_container_id="$(docker create --platform "$arch" alpine:latest)"
|
|
||||||
docker cp "$temp_container_id":/etc/group ./group 1>&2
|
|
||||||
docker cp "$temp_container_id":/etc/passwd ./passwd 1>&2
|
|
||||||
docker rm "$temp_container_id" 1>&2
|
|
||||||
|
|
||||||
echo "coder:x:1000:coder" >>./group
|
|
||||||
echo "coder:x:1000:1000::/:/bin/sh" >>./passwd
|
|
||||||
mkdir ./empty-dir
|
|
||||||
|
|
||||||
docker buildx build \
|
|
||||||
--platform "$arch" \
|
--platform "$arch" \
|
||||||
|
--build-arg "BASE_IMAGE=$base_image" \
|
||||||
--build-arg "CODER_VERSION=$version" \
|
--build-arg "CODER_VERSION=$version" \
|
||||||
|
--no-cache \
|
||||||
--tag "$image_tag" \
|
--tag "$image_tag" \
|
||||||
|
-f Dockerfile \
|
||||||
. 1>&2
|
. 1>&2
|
||||||
|
|
||||||
cdroot
|
cdroot
|
||||||
|
|
|
@ -47,8 +47,9 @@ rcodesign encode-app-store-connect-api-key \
|
||||||
# The notarization process is very fragile and heavily dependent on Apple's
|
# The notarization process is very fragile and heavily dependent on Apple's
|
||||||
# notarization server not returning server errors, so we retry this step twice
|
# notarization server not returning server errors, so we retry this step twice
|
||||||
# with a delay of 30 seconds between attempts.
|
# with a delay of 30 seconds between attempts.
|
||||||
|
NOTARY_SUBMIT_ATTEMPTS=2
|
||||||
rc=0
|
rc=0
|
||||||
for i in $(seq 1 2); do
|
for i in $(seq 1 $NOTARY_SUBMIT_ATTEMPTS); do
|
||||||
# -v is quite verbose, the default output is pretty good on it's own. Adding
|
# -v is quite verbose, the default output is pretty good on it's own. Adding
|
||||||
# -v makes it dump the credentials used for uploading to Apple's S3 bucket.
|
# -v makes it dump the credentials used for uploading to Apple's S3 bucket.
|
||||||
rcodesign notary-submit \
|
rcodesign notary-submit \
|
||||||
|
@ -58,7 +59,7 @@ for i in $(seq 1 2); do
|
||||||
1>&2 && rc=0 && break || rc=$?
|
1>&2 && rc=0 && break || rc=$?
|
||||||
|
|
||||||
log "rcodesign exit code: $rc"
|
log "rcodesign exit code: $rc"
|
||||||
if [[ $i -lt 5 ]]; then
|
if [[ $i -lt $NOTARY_SUBMIT_ATTEMPTS ]]; then
|
||||||
log
|
log
|
||||||
log "Retrying notarization in 30 seconds"
|
log "Retrying notarization in 30 seconds"
|
||||||
log
|
log
|
||||||
|
|
Loading…
Reference in New Issue