...
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=~7.80 python3=${py_version} libcap htop
130RUN apk upgrade --no-cache
131RUN ln -s /usr/bin/python3 /usr/bin/python
132COPY --from=artifacts /usr/bin/kubectl /usr/bin/kubectl
133COPY --from=artifacts /usr/lib/libyaml* /usr/lib/
134
135# Other installers
136COPY --from=artifacts /opt/image-build /opt/image-build
137RUN /opt/image-build/install.sh
138
139# External Python packages we use
140COPY --from=artifacts /usr/lib/python3.9/site-packages /usr/lib/python3.9/site-packages
141
142# Our envoy. The capabilities here grant the wrapper the ability to use the
143# cap_net_bind_service cap and for Envoy to inherit it.
144COPY --from=envoy /usr/local/bin/envoy-static-stripped /usr/local/bin/envoy
145RUN setcap cap_net_bind_service=ei /usr/local/bin/envoy
146
147# Our Go binaries. See envoy section for setcap info.
148COPY --from=artifacts /opt/ambassador /opt/ambassador
149RUN ln -s /opt/ambassador/bin/* /usr/local/bin/
150RUN setcap cap_net_bind_service=p /opt/ambassador/bin/wrapper
151
152# Our Python code
153COPY --from=artifacts /buildroot/ambassador/python /buildroot/ambassador/python
154RUN cd /buildroot/ambassador/python && python setup.py install
155
156# Delete some things that cause problems for security scanners.
157RUN python -m pip uninstall -y pip
158RUN find / \( -iname '*sqlite*' -o -iname '*gdbm*' -o -iname '*smtplib*' -o -iname '*piptools*' -o -iname '*pip_tools*' -o -iname '*ensurepip*' \) -exec rm -rf -- '{}' \+
159
160# Configuration, Docker demo stuff, the AES WebUI. The /ambassador bit changes
161# in post-install so it's always stale. But it's pretty small, so it's not too
162# bad to re-push every time.
163COPY --from=artifacts /ambassador /ambassador
164COPY --from=artifacts /buildroot/ambassador/demo/config /ambassador/ambassador-demo-config
165COPY --from=artifacts /buildroot/ambassador/demo/services /ambassador/demo-services
166
167# Fix permissions to allow correctly running as a non root user
168# XXX: We could combine everything into one tree in the builder, fix permissions
169# there, and then a use single COPY to get everything and avoid duplicating the
170# (small amount of) data in a new layer for this RUN.
171RUN chgrp -R 0 /ambassador && \
172 chmod -R u+x /ambassador && \
173 chmod -R g=u /ambassador /etc/passwd
174
175WORKDIR /ambassador
176
177# Force the HOME environment variable to a directory that'll always be writeable.
178# We use /tmp/ambassador for this, and make sure it exists in our entrypoint,
179# because trying to create it here in the Dockerfile doesn't always work very
180# well in the face of situations like KAT volume-mounting /tmp/ambassador or
181# the like.
182ENV HOME=/tmp/ambassador
183
184ENTRYPOINT [ "bash", "/buildroot/ambassador/python/entrypoint.sh" ]
View as plain text