diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..4ccee25f2c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +# Anything Git or VSCode related is definitely irrelevant for a build. +.git* +.vscode + +# The docker directory contains other Docker images. +docker + +# The release directory is created by goreleaser and isn't required here. +release + +# Documentation and examples aren't needed. +*.md +*.{yaml,yml} diff --git a/.goreleaser.yml b/.goreleaser.yml index 1a39855326..0129b6ec61 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -38,6 +38,7 @@ brews: # Default is the root folder. folder: Formula dockers: + - dockerfile: Dockerfile.release - image_templates: - "sourcegraph/src-cli:{{ .Tag }}" - "sourcegraph/src-cli:{{ .Major }}" diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 8fc2a1d6b1..b8283f7441 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -39,6 +39,30 @@ If a new feature is added to a new `3.91.6` release of src-cli and this change r Note that if instead the recommended src-cli version for Sourcegraph `3.99` was `3.90.4` in the example above, there is no additional step required, and the new patch version of src-cli will be available to both Sourcegraph versions. +## `src-cli` Docker image + +Each release of `src` results in a new tag of the [`sourcegraph/src-cli` Docker image](https://hub.docker.com/r/sourcegraph/src-cli) being pushed to Docker Hub. This is handled by [goreleaser's Docker support](https://goreleaser.com/customization/docker/). + +The main gotcha here is that the way goreleaser builds the Docker image is fairly difficult to replicate from the desktop: it builds a `src` binary without any runtime libc dependencies that can be installed in a `scratch` image, but unless you work on Alpine, your desktop is _not_ configured to build Go binaries like that. + +As a result, there are two Dockerfiles in this project. goreleaser uses `Dockerfile.release`, which is replicated in a multi-stage `Dockerfile` that builds `src` in a builder container to ensure it's built in a way that can be tested. + +### Testing + +If you need to test a change to the Dockerfile (for example, due to a Renovate PR bumping the base image), you should pull that change, then build a local image with something like: + +```bash +docker build -t local-src-cli . +``` + +After which you should be able to run: + +```bash +docker run --rm local-src-cli +``` + +and get the normal help output from `src`. + ## Dependent Docker images `src campaign apply` and `src campaign preview` use a Docker image published as `sourcegraph/src-campaign-volume-workspace` for utility purposes when the volume workspace is selected, which is the default on macOS. This [Docker image](./docker/campaign-volume-workspace/Dockerfile) is built by [a Python script](./docker/campaign-volume-workspace/push.py) invoked by the GitHub Action workflow described in [`docker.yml`](.github/workflows/docker.yml). diff --git a/Dockerfile b/Dockerfile index 92f8ade6c0..528d0f3a9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,20 @@ +# Since we're going to provide images based on Alpine, we also want to build on +# Alpine, rather than relying on the ./src in the surrounding environment to be +# sane. +# +# Nothing fancy here: we copy in the source code and build on the Alpine Go +# image. Refer to .dockerignore to get a sense of what we're not going to copy. +FROM golang:1.15-alpine as builder + +COPY . /src +WORKDIR /src +RUN go build ./cmd/src + +# This stage should be kept in sync with Dockerfile.release. FROM sourcegraph/alpine:3.12@sha256:133a0a767b836cf86a011101995641cf1b5cbefb3dd212d78d7be145adde636d # needed for `src lsif upload` and `src actions exec` RUN apk add --no-cache git -COPY src /usr/bin/ +COPY --from=builder /src/src /usr/bin/ ENTRYPOINT ["/usr/bin/src"] diff --git a/Dockerfile.release b/Dockerfile.release new file mode 100644 index 0000000000..077958151c --- /dev/null +++ b/Dockerfile.release @@ -0,0 +1,11 @@ +# This Dockerfile is used by goreleaser when publishing a release, and is not +# suitable for testing, since it depends on a src binary being at the project +# root _and_ that src binary being runnable on Alpine. To test this, refer to +# the main Dockerfile, which should have an identical second stage. +FROM sourcegraph/alpine:3.12@sha256:133a0a767b836cf86a011101995641cf1b5cbefb3dd212d78d7be145adde636d + +# needed for `src lsif upload` and `src actions exec` +RUN apk add --no-cache git + +COPY src /usr/bin/ +ENTRYPOINT ["/usr/bin/src"]