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
|
||||
wget -O /tmp/nfpm.deb https://github.com/goreleaser/nfpm/releases/download/v2.18.1/nfpm_amd64.deb
|
||||
sudo dpkg -i /tmp/nfpm.deb
|
||||
rm /tmp/nfpm.deb
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Install a prebuilt binary of rcodesign for linux amd64. Once the
|
||||
# following PR is merged and released upstream, we can download
|
||||
# directly from GitHub releases instead:
|
||||
# https://github.com/indygreg/PyOxidizer/pull/635
|
||||
wget -O /tmp/rcodesign https://cdn.discordapp.com/attachments/283356472258199552/1016767245717872700/rcodesign
|
||||
sudo install --mode 755 /tmp/rcodesign /usr/local/bin/rcodesign
|
||||
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
|
||||
sudo tar -xzf /tmp/rcodesign.tar.gz \
|
||||
-C /usr/bin \
|
||||
--strip-components=1 \
|
||||
apple-codesign-0.22.0-x86_64-unknown-linux-musl/rcodesign
|
||||
rm /tmp/rcodesign.tar.gz
|
||||
|
||||
- name: Setup Apple Developer certificate and API key
|
||||
run: |
|
||||
|
@ -160,6 +160,39 @@ jobs:
|
|||
- name: Delete Apple Developer certificate and API key
|
||||
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
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
|
@ -188,6 +221,8 @@ jobs:
|
|||
--target "$(./scripts/image_tag.sh --version latest)" \
|
||||
$(cat build/coder_"$version"_linux_{amd64,arm64,armv7}.tag)
|
||||
fi
|
||||
env:
|
||||
CODER_BASE_IMAGE_TAG: ${{ steps.image-base-tag.outputs.tag }}
|
||||
|
||||
- name: ls build
|
||||
run: ls -lh build
|
||||
|
@ -252,6 +287,14 @@ jobs:
|
|||
./build/*.rpm
|
||||
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:
|
||||
name: Publish to winget-pkgs
|
||||
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
|
||||
# different repo.
|
||||
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
|
||||
run: |
|
||||
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
|
||||
|
||||
- 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
|
||||
# using the go toolchain on the host and then copied into the build context by
|
||||
# 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
|
||||
# in the build script.
|
||||
|
@ -14,17 +18,7 @@ LABEL \
|
|||
org.opencontainers.image.source="https://github.com/coder/coder" \
|
||||
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.
|
||||
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" ]
|
||||
|
|
|
@ -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
|
||||
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
|
||||
# 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 && \
|
||||
|
|
|
@ -3,12 +3,19 @@
|
|||
# This script builds a Docker image of Coder containing the given binary, for
|
||||
# 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
|
||||
# will be automatically mapped to a suitable architecture that Docker accepts
|
||||
# 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
|
||||
# ./image_tag.sh unless a --target parameter is supplied.
|
||||
#
|
||||
|
@ -22,12 +29,15 @@ set -euo pipefail
|
|||
# shellcheck source=scripts/lib.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
||||
|
||||
DEFAULT_BASE="${CODER_BASE_IMAGE_TAG:-ghcr.io/coder/coder-base:latest}"
|
||||
|
||||
arch=""
|
||||
image_tag=""
|
||||
build_base="${CODER_IMAGE_BUILD_BASE_TAG:-}"
|
||||
version=""
|
||||
push=0
|
||||
|
||||
args="$(getopt -o "" -l arch:,target:,version:,push -- "$@")"
|
||||
args="$(getopt -o "" -l arch:,target:,build-base:,version:,push -- "$@")"
|
||||
eval set -- "$args"
|
||||
while true; do
|
||||
case "$1" in
|
||||
|
@ -43,6 +53,10 @@ while true; do
|
|||
version="$2"
|
||||
shift 2
|
||||
;;
|
||||
--build-base)
|
||||
build_base="$2"
|
||||
shift
|
||||
;;
|
||||
--push)
|
||||
push=1
|
||||
shift
|
||||
|
@ -98,31 +112,37 @@ fi
|
|||
cdroot
|
||||
temp_dir="$(TMPDIR="$(dirname "$input_file")" mktemp -d)"
|
||||
ln "$input_file" "$temp_dir/coder"
|
||||
ln Dockerfile.base "$temp_dir/"
|
||||
ln Dockerfile "$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)"
|
||||
|
||||
# Pull the base image, copy the /etc/group and /etc/passwd files out of it, and
|
||||
# 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 \
|
||||
docker build \
|
||||
--platform "$arch" \
|
||||
--build-arg "BASE_IMAGE=$base_image" \
|
||||
--build-arg "CODER_VERSION=$version" \
|
||||
--no-cache \
|
||||
--tag "$image_tag" \
|
||||
-f Dockerfile \
|
||||
. 1>&2
|
||||
|
||||
cdroot
|
||||
|
|
|
@ -47,8 +47,9 @@ rcodesign encode-app-store-connect-api-key \
|
|||
# The notarization process is very fragile and heavily dependent on Apple's
|
||||
# notarization server not returning server errors, so we retry this step twice
|
||||
# with a delay of 30 seconds between attempts.
|
||||
NOTARY_SUBMIT_ATTEMPTS=2
|
||||
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 makes it dump the credentials used for uploading to Apple's S3 bucket.
|
||||
rcodesign notary-submit \
|
||||
|
@ -58,7 +59,7 @@ for i in $(seq 1 2); do
|
|||
1>&2 && rc=0 && break || rc=$?
|
||||
|
||||
log "rcodesign exit code: $rc"
|
||||
if [[ $i -lt 5 ]]; then
|
||||
if [[ $i -lt $NOTARY_SUBMIT_ATTEMPTS ]]; then
|
||||
log
|
||||
log "Retrying notarization in 30 seconds"
|
||||
log
|
||||
|
|
Loading…
Reference in New Issue