...
1# syntax = docker/dockerfile:1.3
2
3###
4# This dockerfile builds all the source code and docker images for the
5# edge stack.
6##
7
8###
9# How it works.
10##
11# All our source code is built in a single monolithic build
12# container. (The "builder" stage below.) We then produce optimized
13# release images by copying the specific binaries and entrypoints out
14# of the build container. The build container must always contain all
15# the binaries and entrypoints for any container we produce, and
16# therefore (with the appropriate entrypoint) can function in place of
17# any release container. The release containers are trivial stages
18# that simply copy the relevant artifacts out of the builder
19# container.
20
21# This argument controls the base image that is used for the release
22# containers.
23ARG base="i-forgot-to-set-build-arg-base"
24
25# This argument sets the base image for the build container image. This
26# base image contains only third-party code.
27ARG builderbase="i-forgot-to-set-build-arg-builderbase"
28
29# This controls where we copy envoy from.
30ARG envoy="i-forgot-to-set-build-arg-envoy"
31
32########################################
33# The builder image
34########################################
35
36FROM ${envoy} as envoy
37
38FROM ${builderbase} as builder
39
40WORKDIR /buildroot
41
42ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/buildroot/bin
43
44COPY --from=envoy /usr/local/bin/envoy-static-stripped /usr/local/bin/envoy
45
46ENV KUBECONFIG=/buildroot/kubeconfig.yaml
47
48# XXX: this will go away
49RUN mkdir -p /ambassador/sidecars && \
50 ln -s /buildroot/ambassador/python/post_update.py /ambassador/post_update.py && \
51 ln -s /buildroot/ambassador/python/watch_hook.py /ambassador/watch_hook.py && \
52 ln -s /buildroot/ambassador/python/kubewatch.py /ambassador/kubewatch.py
53
54RUN adduser dw --disabled-password
55# SUDO_USERS HOSTS=(AS_USER) TAGS COMMANDS
56RUN echo "dw ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/datawire
57RUN chown dw /buildroot
58USER dw
59
60ENTRYPOINT [ "/bin/bash" ]
61
62########################################
63# The golang build stage
64########################################
65
66FROM ${builderbase} as golang
67
68WORKDIR /go
69
70ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/buildroot/bin
71
72# Build the golang binaries
73ADD api api
74ADD cmd cmd
75ADD pkg pkg
76ADD vendor vendor
77ADD go.mod go.mod
78ADD go.sum go.sum
79
80RUN --mount=type=cache,target=/root/.cache/go-build \
81 mkdir -p /go/bin && \
82 time go build -mod=vendor -o /go/bin/ ./cmd/...
83
84########################################
85# The artifact build stage
86########################################
87
88FROM ${builderbase} as artifacts
89
90WORKDIR /buildroot/ambassador
91
92ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/buildroot/bin
93
94# Copy in the golang binaries
95COPY --from=golang /go/bin/* /buildroot/bin/
96
97# Setup the python code
98ADD python python
99RUN time pip install --no-deps -e python
100
101# Run post-compile.sh
102ADD build-aux build-aux
103ADD post-compile.sh post-compile.sh
104RUN bash post-compile.sh
105
106# XXX: this will go away
107RUN mkdir -p /ambassador/sidecars && \
108 ln -s /buildroot/ambassador/python/post_update.py /ambassador/post_update.py && \
109 ln -s /buildroot/ambassador/python/watch_hook.py /ambassador/watch_hook.py && \
110 ln -s /buildroot/ambassador/python/kubewatch.py /ambassador/kubewatch.py
111
112# These will be extracted into the optimized image later
113ADD demo demo
114ADD manifests/emissary/emissary-crds.yaml.in manifests/emissary/emissary-crds.yaml
115
116########################################
117# The optimized images
118########################################
119
120FROM ${base} as ambassador
121
122ARG py_version="i-forgot-to-set-build-arg-py-version"
123
124# Always have an "ambassador" user as UID 8888. This is what we recommend
125# people run as. (Note that the "-D" actually leaves the password locked.)
126RUN adduser ambassador -u 8888 -G root -D -H -s /bin/false
127
128# External stuff that should change infrequently
129RUN apk --no-cache add bash curl python3=${py_version} libcap htop
130RUN apk upgrade --no-cache
131COPY --from=artifacts /usr/lib/libyaml* /usr/lib/
132
133# Other installers
134COPY --from=artifacts /opt/image-build /opt/image-build
135RUN /opt/image-build/install.sh
136
137# External Python packages we use
138COPY --from=artifacts /usr/lib/python3.10/site-packages /usr/lib/python3.10/site-packages
139
140# Our envoy. The capabilities here grant the wrapper the ability to use the
141# cap_net_bind_service cap and for Envoy to inherit it.
142COPY --from=envoy /usr/local/bin/envoy-static-stripped /usr/local/bin/envoy
143RUN setcap cap_net_bind_service=ei /usr/local/bin/envoy
144
145# Our Go binaries. See envoy section for setcap info.
146COPY --from=artifacts /opt/ambassador /opt/ambassador
147RUN ln -s /opt/ambassador/bin/* /usr/local/bin/
148RUN setcap cap_net_bind_service=p /opt/ambassador/bin/wrapper
149
150# Our Python code
151COPY --from=artifacts /buildroot/ambassador/python /buildroot/ambassador/python
152RUN cd /buildroot/ambassador/python && python setup.py install
153
154# Delete some things that cause problems for security scanners.
155RUN python -m pip uninstall -y pip
156RUN find / \( -iname '*sqlite*' -o -iname '*gdbm*' -o -iname '*smtplib*' -o -iname '*piptools*' -o -iname '*pip_tools*' -o -iname '*ensurepip*' \) -exec rm -rf -- '{}' \+
157
158# Configuration, Docker demo stuff, the AES WebUI. The /ambassador bit changes
159# in post-install so it's always stale. But it's pretty small, so it's not too
160# bad to re-push every time.
161COPY --from=artifacts /ambassador /ambassador
162COPY --from=artifacts /buildroot/ambassador/demo/config /ambassador/ambassador-demo-config
163COPY --from=artifacts /buildroot/ambassador/demo/services /ambassador/demo-services
164
165# Fix permissions to allow correctly running as a non root user
166# XXX: We could combine everything into one tree in the builder, fix permissions
167# there, and then a use single COPY to get everything and avoid duplicating the
168# (small amount of) data in a new layer for this RUN.
169RUN chgrp -R 0 /ambassador && \
170 chmod -R u+x /ambassador && \
171 chmod -R g=u /ambassador /etc/passwd
172
173WORKDIR /ambassador
174
175# Force the HOME environment variable to a directory that'll always be writeable.
176# We use /tmp/ambassador for this, and make sure it exists in our entrypoint,
177# because trying to create it here in the Dockerfile doesn't always work very
178# well in the face of situations like KAT volume-mounting /tmp/ambassador or
179# the like.
180ENV HOME=/tmp/ambassador
181
182ENTRYPOINT [ "bash", "/buildroot/ambassador/python/entrypoint.sh" ]
View as plain text