Skip to content

Commit 310aff8

Browse files
GenPagenitrocode
andauthored
refactor(atlantis-image): recombine with atlantis-base (#3001)
* refactor: atlantis-image build pipeline and docker images Atlantis built and maintained two separate docker images, atlantis and atlantis-base. This made cutting releases cumbersome and had inefficiencies in the docker image layers. This PR condenses the workflow into a single job and Dockerfile once again by utilizing multi-stage builds more heavily and Docker build targeting. * fix: apply @nitrocode suggestions from code review * feat: hadolint * fix: DL4006 on go mod graph * fix: version regressions --------- Co-authored-by: nitrocode <[email protected]>
1 parent 089dc1a commit 310aff8

File tree

6 files changed

+176
-294
lines changed

6 files changed

+176
-294
lines changed

.github/workflows/atlantis-base.yml

-98
This file was deleted.

.github/workflows/atlantis-image.yml

+25
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
pull_request:
1111
paths:
1212
- 'Dockerfile'
13+
- 'docker-entrypoint.sh'
1314
- '.github/workflows/atlantis-image.yml'
1415
workflow_dispatch:
1516

@@ -32,6 +33,12 @@ jobs:
3233
steps:
3334
- uses: actions/checkout@v3
3435

36+
# Lint the Dockerfile first before setting anything up
37+
- name: Lint Dockerfile
38+
uses: hadolint/hadolint-action@master
39+
with:
40+
dockerfile: "Dockerfile"
41+
3542
- name: Set up QEMU
3643
uses: docker/setup-qemu-action@v2
3744
with:
@@ -56,6 +63,7 @@ jobs:
5663
images: |
5764
${{ env.DOCKER_REPO }}
5865
labels: |
66+
org.opencontainers.image.authors="Anubhav Mishra, Luke Kysow"
5967
org.opencontainers.image.licenses=Apache-2.0
6068
tags: |
6169
# semver
@@ -86,6 +94,22 @@ jobs:
8694
username: ${{ github.actor }}
8795
password: ${{ secrets.GITHUB_TOKEN }}
8896

97+
# Publish dev image to container registry
98+
- name: Build and push atlantis:dev${{ env.IMAGE_SUFFIX }} image
99+
if: ${{ contains(fromJson('["push", "pull_request"]'), github.event_name) }}
100+
uses: docker/build-push-action@v3
101+
with:
102+
cache-from: type=gha
103+
cache-to: type=gha,mode=max
104+
context: .
105+
platforms: linux/arm64/v8,linux/amd64,linux/arm/v7
106+
push: ${{ github.event_name != 'pull_request' }}
107+
tags: |
108+
ghcr.io/${{ github.repository_owner }}/atlantis:dev${{ env.IMAGE_SUFFIX }}
109+
ghcr.io/${{ github.repository_owner }}/atlantis:dev-${{ matrix.image_type }}
110+
target: ${{ matrix.image_type }}
111+
labels: ${{ steps.meta.outputs.labels }}
112+
89113
# Publish release to container registry
90114
- name: Populate release version
91115
if: contains(fromJson('["push", "pull_request"]'), github.event_name)
@@ -106,5 +130,6 @@ jobs:
106130
platforms: linux/arm64/v8,linux/amd64,linux/arm/v7
107131
push: ${{ env.PUSH }}
108132
tags: ${{ steps.meta.outputs.tags }}
133+
target: ${{ matrix.image_type }}
109134
labels: ${{ steps.meta.outputs.labels }}
110135
outputs: type=image,name=target,annotation-index.org.opencontainers.image.description=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.description'] }}

Dockerfile

+151-31
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
ARG ATLANTIS_BASE=ghcr.io/runatlantis/atlantis-base
2-
ARG ATLANTIS_BASE_TAG_DATE=latest
3-
ARG ATLANTIS_BASE_TAG_TYPE=alpine
1+
# syntax=docker/dockerfile:1
2+
# what distro is the image being built for
3+
ARG ALPINE_TAG=3.17.1
4+
ARG DEBIAN_TAG=11.6-slim
45

5-
# Stage 1: build artifact
6+
# Stage 1: build artifact and download deps
67

78
FROM golang:1.20.2-alpine AS builder
89

@@ -19,28 +20,102 @@ WORKDIR /app
1920
# https://github.com/montanaflynn/golang-docker-cache
2021
# https://github.com/golang/go/issues/27719
2122
COPY go.mod go.sum ./
23+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
2224
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
2325

2426
COPY . /app
25-
2627
RUN --mount=type=cache,target=/go/pkg/mod \
2728
--mount=type=cache,target=/root/.cache/go-build \
2829
CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X 'main.version=${ATLANTIS_VERSION}' -X 'main.commit=${ATLANTIS_COMMIT}' -X 'main.date=${ATLANTIS_DATE}'" -v -o atlantis .
2930

30-
# Stage 2
31-
# The runatlantis/atlantis-base is created by docker-base/Dockerfile
32-
FROM ${ATLANTIS_BASE}:${ATLANTIS_BASE_TAG_DATE}-${ATLANTIS_BASE_TAG_TYPE} AS base
31+
FROM debian:${DEBIAN_TAG} as deps
3332

3433
# Get the architecture the image is being built for
3534
ARG TARGETPLATFORM
35+
WORKDIR /tmp/build
36+
37+
# Install packages needed for building/verifying dependencies
38+
# hadolint ignore=DL3008,SC2261
39+
RUN apt-get update \
40+
&& apt-get install -y --no-install-recommends \
41+
ca-certificates>=20210119 \
42+
curl>=7.74 \
43+
git>=1:2.30 \
44+
unzip>=6.0 \
45+
bash>=5.1 \
46+
openssh-server>=1:8.4p1 \
47+
libcap2>=1:2.44 \
48+
dumb-init>=1.2 \
49+
gnupg>=2.2 \
50+
openssl>=1.1.1n
51+
52+
# install conftest
53+
# renovate: datasource=github-releases depName=open-policy-agent/conftest
54+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
55+
ENV DEFAULT_CONFTEST_VERSION=0.40.0
56+
RUN AVAILABLE_CONFTEST_VERSIONS=${DEFAULT_CONFTEST_VERSION} && \
57+
case ${TARGETPLATFORM} in \
58+
"linux/amd64") CONFTEST_ARCH=x86_64 ;; \
59+
"linux/arm64") CONFTEST_ARCH=arm64 ;; \
60+
# There is currently no compiled version of conftest for armv7
61+
"linux/arm/v7") CONFTEST_ARCH=x86_64 ;; \
62+
esac && \
63+
for VERSION in ${AVAILABLE_CONFTEST_VERSIONS}; do \
64+
curl -LOs "https://github.com/open-policy-agent/conftest/releases/download/v${VERSION}/conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz" && \
65+
curl -LOs "https://github.com/open-policy-agent/conftest/releases/download/v${VERSION}/checksums.txt" && \
66+
sed -n "/conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz/p" checksums.txt | sha256sum -c && \
67+
mkdir -p "/usr/local/bin/cft/versions/${VERSION}" && \
68+
tar -C "/usr/local/bin/cft/versions/${VERSION}" -xzf "conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz" && \
69+
ln -s "/usr/local/bin/cft/versions/${VERSION}/conftest" /usr/local/bin/conftest && \
70+
rm "conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz" && \
71+
rm checksums.txt; \
72+
done
73+
74+
# install gosu
75+
# We use gosu to step down from root and run as the atlantis user
76+
# renovate: datasource=github-releases depName=tianon/gosu
77+
ENV GOSU_VERSION=1.16
78+
79+
RUN case ${TARGETPLATFORM} in \
80+
"linux/amd64") GOSU_ARCH=amd64 ;; \
81+
"linux/arm64") GOSU_ARCH=arm64 ;; \
82+
"linux/arm/v7") GOSU_ARCH=armhf ;; \
83+
esac && \
84+
curl -L -s --output gosu "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${GOSU_ARCH}" && \
85+
curl -L -s --output gosu.asc "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${GOSU_ARCH}.asc" && \
86+
for server in $(shuf -e ipv4.pool.sks-keyservers.net \
87+
hkp://p80.pool.sks-keyservers.net:80 \
88+
keyserver.ubuntu.com \
89+
hkp://keyserver.ubuntu.com:80 \
90+
pgp.mit.edu) ; do \
91+
gpg --keyserver "$server" --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && break || : ; \
92+
done && \
93+
gpg --batch --verify gosu.asc gosu && \
94+
chmod +x gosu && \
95+
cp gosu /bin && \
96+
gosu --version
97+
98+
# install git-lfs
99+
# renovate: datasource=github-releases depName=git-lfs/git-lfs
100+
ENV GIT_LFS_VERSION=3.3.0
101+
102+
RUN case ${TARGETPLATFORM} in \
103+
"linux/amd64") GIT_LFS_ARCH=amd64 ;; \
104+
"linux/arm64") GIT_LFS_ARCH=arm64 ;; \
105+
"linux/arm/v7") GIT_LFS_ARCH=arm ;; \
106+
esac && \
107+
curl -L -s --output git-lfs.tar.gz "https://github.com/git-lfs/git-lfs/releases/download/v${GIT_LFS_VERSION}/git-lfs-linux-${GIT_LFS_ARCH}-v${GIT_LFS_VERSION}.tar.gz" && \
108+
tar --strip-components=1 -xf git-lfs.tar.gz && \
109+
chmod +x git-lfs && \
110+
mv git-lfs /usr/bin/git-lfs && \
111+
git-lfs --version
36112

37113
# install terraform binaries
38114
# renovate: datasource=github-releases depName=hashicorp/terraform versioning=hashicorp
39115
ENV DEFAULT_TERRAFORM_VERSION=1.4.4
40116

41-
# In the official Atlantis image we only have the latest of each Terraform version.
42-
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
43-
RUN AVAILABLE_TERRAFORM_VERSIONS="1.0.11 1.1.9 1.2.9 1.3.9 ${DEFAULT_TERRAFORM_VERSION}" && \
117+
# In the official Atlantis image, we only have the latest of each Terraform version.
118+
RUN AVAILABLE_TERRAFORM_VERSIONS="1.1.9 1.2.9 1.3.9 ${DEFAULT_TERRAFORM_VERSION}" && \
44119
case "${TARGETPLATFORM}" in \
45120
"linux/amd64") TERRAFORM_ARCH=amd64 ;; \
46121
"linux/arm64") TERRAFORM_ARCH=arm64 ;; \
@@ -59,34 +134,79 @@ RUN AVAILABLE_TERRAFORM_VERSIONS="1.0.11 1.1.9 1.2.9 1.3.9 ${DEFAULT_TERRAFORM_V
59134
done && \
60135
ln -s "/usr/local/bin/tf/versions/${DEFAULT_TERRAFORM_VERSION}/terraform" /usr/local/bin/terraform
61136

62-
# renovate: datasource=github-releases depName=open-policy-agent/conftest
63-
ENV DEFAULT_CONFTEST_VERSION=0.40.0
64137

65-
RUN AVAILABLE_CONFTEST_VERSIONS="${DEFAULT_CONFTEST_VERSION}" && \
66-
case "${TARGETPLATFORM}" in \
67-
"linux/amd64") CONFTEST_ARCH=x86_64 ;; \
68-
"linux/arm64") CONFTEST_ARCH=arm64 ;; \
69-
# There is currently no compiled version of conftest for armv7
70-
"linux/arm/v7") CONFTEST_ARCH=x86_64 ;; \
71-
esac && \
72-
for VERSION in ${AVAILABLE_CONFTEST_VERSIONS}; do \
73-
curl -LOs "https://github.com/open-policy-agent/conftest/releases/download/v${VERSION}/conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz" && \
74-
curl -LOs "https://github.com/open-policy-agent/conftest/releases/download/v${VERSION}/checksums.txt" && \
75-
sed -n "/conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz/p" checksums.txt | sha256sum -c && \
76-
mkdir -p "/usr/local/bin/cft/versions/${VERSION}" && \
77-
tar -C "/usr/local/bin/cft/versions/${VERSION}" -xzf "conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz" && \
78-
ln -s "/usr/local/bin/cft/versions/${VERSION}/conftest" "/usr/local/bin/conftest${VERSION}" && \
79-
rm "conftest_${VERSION}_Linux_${CONFTEST_ARCH}.tar.gz" && \
80-
rm checksums.txt; \
81-
done
138+
# Stage 2 - Alpine
139+
# Creating the individual distro builds using targets
140+
FROM alpine:${ALPINE_TAG} AS alpine
82141

83-
RUN ln -s /usr/local/bin/cft/versions/${DEFAULT_CONFTEST_VERSION}/conftest /usr/local/bin/conftest
142+
# atlantis user for gosu and OpenShift compatibility
143+
RUN addgroup atlantis && \
144+
adduser -S -G atlantis atlantis && \
145+
adduser atlantis root && \
146+
chown atlantis:root /home/atlantis/ && \
147+
chmod g=u /home/atlantis/ && \
148+
chmod g=u /etc/passwd
84149

85150
# copy binary
86151
COPY --from=builder /app/atlantis /usr/local/bin/atlantis
152+
# copy terraform
153+
COPY --from=deps /usr/local/bin/terraform* /usr/local/bin/
154+
# copy deps
155+
COPY --from=deps /usr/local/bin/conftest /usr/local/bin/conftest
156+
COPY --from=deps /bin/gosu /bin/gosu
157+
COPY --from=deps /usr/bin/git-lfs /usr/bin/git-lfs
158+
# copy docker entrypoint
159+
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
160+
161+
# Install packages needed for running Atlantis.
162+
# We place this last as it will bust less docker layer caches when packages update
163+
RUN apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main/ \
164+
git~=2.40 && \
165+
apk add --no-cache \
166+
ca-certificates~=20220614 \
167+
curl~=7.87 \
168+
unzip~=6.0 \
169+
bash~=5.2 \
170+
openssh~=9.1_p1 \
171+
libcap~=2.66 \
172+
dumb-init~=1.2 \
173+
gcompat~=1.1
87174

175+
ENTRYPOINT ["docker-entrypoint.sh"]
176+
CMD ["server"]
177+
178+
# Stage 2 - Debian
179+
FROM debian:${DEBIAN_TAG} AS debian
180+
181+
# copy binary
182+
COPY --from=builder /app/atlantis /usr/local/bin/atlantis
183+
# copy terraform
184+
COPY --from=deps /usr/local/bin/terraform* /usr/local/bin/
185+
# copy deps
186+
COPY --from=deps /usr/local/bin/conftest /usr/local/bin/conftest
187+
COPY --from=deps /bin/gosu /bin/gosu
188+
COPY --from=deps /usr/bin/git-lfs /usr/bin/git-lfs
88189
# copy docker entrypoint
89190
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
90191

192+
# Install packages needed for running Atlantis.
193+
# We place this last as it will bust less docker layer caches when packages update
194+
# hadolint ignore explanation
195+
# DL3008 (pin versions using "=") - Ignored to avoid failing the build
196+
# SC2261 (multiple redirections) - This is a bug https://github.com/hadolint/hadolint/issues/782
197+
# hadolint ignore=DL3008,SC2261
198+
RUN apt-get update && \
199+
apt-get install -y --no-install-recommends \
200+
ca-certificates>=20210119 \
201+
curl>=7.74 \
202+
git>=1:2.30 \
203+
unzip>=6.0 \
204+
bash>=5.1 \
205+
openssh-server>=1:8.4p1 \
206+
libcap2>=1:2.44 \
207+
dumb-init>=1.2 && \
208+
apt-get clean && \
209+
rm -rf /var/lib/apt/lists/*
210+
91211
ENTRYPOINT ["docker-entrypoint.sh"]
92212
CMD ["server"]

Dockerfile.dev

-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
FROM ghcr.io/runatlantis/atlantis:latest
22
COPY atlantis /usr/local/bin/atlantis
3-
# TODO: remove this once we get this in the base image
4-
# renovate: datasource=github-releases depName=open-policy-agent/conftest
5-
ENV DEFAULT_CONFTEST_VERSION=0.40.0
6-
73
WORKDIR /atlantis/src

0 commit comments

Comments
 (0)