docker: Use buildkit for caching (#472)

Our docker builds do not permit caching of dependencies or intermediate
build artifacts. However, Docker's new (experimental) buildkit features
add this functionality. I've been using this configuration locally for
some time, and it seems generaly useful enough to promote (especially
since this Dockerfile is only intended for development).

This change also untroduces the `PROXY_FEATURES` build-arg so that the
Dockerfile can be used to support profiling builds.

Furthermore, the `update-rust-versions.sh` script has been updated to
check versions and be more permissive about how it replaces versions in
the Dockerfile.

The docker CI build has been disabled until GitHub Actions has support
for this Dockerfile format.
This commit is contained in:
Oliver Gould 2020-04-13 14:57:58 -07:00 committed by GitHub
parent feed830285
commit d27b79cd7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 64 deletions

View File

@ -6,14 +6,14 @@ name: Docker
on: on:
push: push:
branches: branches:
- master - master
paths: paths:
- 'Cargo.lock' - "Cargo.lock"
- 'Dockerfile' - "Dockerfile"
pull_request: pull_request:
paths: paths:
- 'Cargo.lock' - "Cargo.lock"
- 'Dockerfile' - "Dockerfile"
env: env:
DOCKER_UNOPTIMIZED: "1" DOCKER_UNOPTIMIZED: "1"
@ -22,43 +22,43 @@ jobs:
docker: docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
# Create a build image on a Linkerd build host. # Create a build image on a Linkerd build host.
- name: Setup (Origin) - name: Setup (Origin)
if: '!github.event.pull_request.head.repo.fork' if: "!github.event.pull_request.head.repo.fork"
run: | run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
# Create an identity file and protect before writing contents to it. # Create an identity file and protect before writing contents to it.
touch ~/.ssh/id && chmod 600 ~/.ssh/id touch ~/.ssh/id && chmod 600 ~/.ssh/id
echo "${{ secrets.DOCKER_PRIVATE_KEY }}" >~/.ssh/id echo "${{ secrets.DOCKER_PRIVATE_KEY }}" >~/.ssh/id
# Use well-known public keys for the host to prevent middlemen. # Use well-known public keys for the host to prevent middlemen.
echo "${{ secrets.DOCKER_KNOWN_HOSTS }}" >~/.ssh/known_hosts echo "${{ secrets.DOCKER_KNOWN_HOSTS }}" >~/.ssh/known_hosts
# Configure host with ServerAliveInterval to ensure that the client # Configure host with ServerAliveInterval to ensure that the client
# stays alive even when the server is busy emitting nothing. # stays alive even when the server is busy emitting nothing.
# ServerAliveCountMax ensures that server responds to these pings # ServerAliveCountMax ensures that server responds to these pings
# within ~5 minutes. # within ~5 minutes.
( (
echo "Host linkerd-docker" echo "Host linkerd-docker"
echo " User github" echo " User github"
echo " Hostname ${{ secrets.DOCKER_ADDRESS }}" echo " Hostname ${{ secrets.DOCKER_ADDRESS }}"
echo " IdentityFile ~/.ssh/id" echo " IdentityFile ~/.ssh/id"
echo " BatchMode yes" echo " BatchMode yes"
echo " ServerAliveInterval 60" echo " ServerAliveInterval 60"
echo " ServerAliveCountMax 5" echo " ServerAliveCountMax 5"
) >~/.ssh/config ) >~/.ssh/config
# Confirm that the SSH configuration works. # Confirm that the SSH configuration works.
ssh linkerd-docker docker version ssh linkerd-docker docker version
- name: Docker (Origin) - name: Docker (Origin)
if: '!github.event.pull_request.head.repo.fork' if: "!github.event.pull_request.head.repo.fork"
env: env:
DOCKER_HOST: "ssh://linkerd-docker" DOCKER_HOST: "ssh://linkerd-docker"
run: | run: |
export DOCKER_TAG="proxy-ci:$(dd bs=64 count=1 if=/dev/urandom status=none | tr -dc 'a-zA-Z0-9')" export DOCKER_TAG="proxy-ci:$(dd bs=64 count=1 if=/dev/urandom status=none | tr -dc 'a-zA-Z0-9')"
make docker make docker
docker image rm -f "$DOCKER_TAG" docker image rm -f "$DOCKER_TAG"
- name: Docker (Fork) - name: Docker (Fork)
if: github.event.pull_request.head.repo.fork if: github.event.pull_request.head.repo.fork
run: make docker run: make docker

View File

@ -1,36 +1,56 @@
# syntax=docker/dockerfile:experimental
# Proxy build and runtime # Proxy build and runtime
# #
# This is intended **DEVELOPMENT ONLY**, i.e. so that proxy developers can # This is intended **DEVELOPMENT ONLY**, i.e. so that proxy developers can
# easily test the proxy in the context of the larger `linkerd2` project. # easily test the proxy in the context of the larger `linkerd2` project.
# #
# When PROXY_UNOPTIMIZED is set and not empty, unoptimized rust artifacts are produced. # This Dockerfile requires expirmental features to be enabled in both the
# This reduces build time and produces binaries with debug symbols, at the expense of # Docker client and daemon. You MUST use buildkit to build this image. The
# runtime performance. # simplest way to do this is to set the `DOCKER_BUILDKIT` environment variable:
#
# :; DOCKER_BUILDKIT=1 docker build .
#
# Alternatively, you can use `buildx`, which supports more complicated build
# configurations:
#
# :; docker buildx build . --load
# rather than updating this manually, run update-rust-version.sh # Please make changes via update-rust-version.sh
ARG RUST_IMAGE=rust:1.41.0-buster ARG RUST_IMAGE=rust:1.41.0-buster
ARG RUNTIME_IMAGE=gcr.io/linkerd-io/proxy:edge-20.2.2
ARG PROXY_UNOPTIMIZED
## Builds the proxy as incrementally as possible. # Use an arbitrary ~recent edge release image to get the proxy
# identity-initializing wrapper.
ARG RUNTIME_IMAGE=gcr.io/linkerd-io/proxy:edge-20.4.1
# Build the proxy, leveraging (new, experimental) cache mounting.
#
# See: https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md#run---mounttypecache
FROM $RUST_IMAGE as build FROM $RUST_IMAGE as build
# When set, causes the proxy to be compiled in development mode.
ARG PROXY_UNOPTIMIZED
# Controls what features are enabled in the proxy. This is typically empty but
# may be set to `mock-orig-dst` for profiling builds.
ARG PROXY_FEATURES
WORKDIR /usr/src/linkerd2-proxy WORKDIR /usr/src/linkerd2-proxy
COPY . . COPY . .
RUN cargo fetch --locked RUN --mount=type=cache,target=target \
RUN if [ -n "$PROXY_UNOPTIMIZED" ]; \ --mount=type=cache,from=rust:1.41.0-buster,source=/usr/local/cargo,target=/usr/local/cargo \
then \ mkdir -p /out && \
cargo build -p linkerd2-proxy --bin linkerd2-proxy --frozen && \ if [ -n "$PROXY_UNOPTIMIZED" ]; then \
mv target/debug/linkerd2-proxy target/linkerd2-proxy ; \ (cd linkerd2-proxy && cargo build --locked --features="$PROXY_FEATURES") && \
mv target/debug/linkerd2-proxy /out/linkerd2-proxy ; \
else \ else \
cargo build -p linkerd2-proxy --bin linkerd2-proxy --frozen --release && \ (cd linkerd2-proxy && cargo build --locked --release --features="$PROXY_FEATURES") && \
mv target/release/linkerd2-proxy target/linkerd2-proxy ; \ mv target/release/linkerd2-proxy /out/linkerd2-proxy ; \
fi fi
## Install the proxy binary into the base runtime image. ## Install the proxy binary into the base runtime image.
FROM $RUNTIME_IMAGE as runtime FROM $RUNTIME_IMAGE as runtime
WORKDIR /linkerd WORKDIR /linkerd
COPY --from=build /usr/src/linkerd2-proxy/target/linkerd2-proxy /usr/lib/linkerd/linkerd2-proxy COPY --from=build /out/linkerd2-proxy /usr/lib/linkerd/linkerd2-proxy
ENV LINKERD2_PROXY_LOG=warn,linkerd2_proxy=info ENV LINKERD2_PROXY_LOG=warn,linkerd=info
# Inherits the ENTRYPOINT from the runtime image.

View File

@ -105,7 +105,7 @@ clean-profile:
.PHONY: docker .PHONY: docker
docker: Dockerfile Cargo.lock docker: Dockerfile Cargo.lock
$(DOCKER_BUILD) . DOCKER_BUILDKIT=1 $(DOCKER_BUILD) .
.PHONY: all .PHONY: all
all: build test all: build test

View File

@ -7,10 +7,14 @@ if [ $# -ne 1 ]; then
exit 64 exit 64
fi fi
VERSION=$1 VERSION="$1"
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$' ; then
echo "Expected M.N.P; got '$VERSION'" >&2
exit 64
fi
echo "$VERSION" > rust-toolchain echo "$VERSION" > rust-toolchain
sed -i'' -e "s/RUST_IMAGE=.*/RUST_IMAGE=rust:$VERSION-buster/" Dockerfile sed -i'' -Ee "s/rust:[0-9]+\.[0-9]+\.[0-9]+/rust:$VERSION/" Dockerfile
find .github -name \*.yml \ find .github -name \*.yml \
-exec sed -i'' -e "s|docker://rust:.*|docker://rust:$VERSION-buster|" '{}' \; -exec sed -i'' -Ee "s|docker://rust:[0-9]+\.[0-9]+\.[0-9]+|docker://rust:$VERSION|" '{}' \;