Skip to content

Commit a73ade9

Browse files
committed
Move Docker build info public
0 parents  commit a73ade9

27 files changed

+1017
-0
lines changed

Dockerfile

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
###############################################################################
2+
#
3+
# Multi-stage Python 3.x build
4+
#
5+
# build-time environment variables:
6+
# LTO=1 . enable link-time-optimizations
7+
# OPTIMAL=1 . enable profile-guided-optimizations (PGO)
8+
# PYTHON_VERSION=3.5.3
9+
#
10+
# ** NOTE **:
11+
# . LTO requires PGO
12+
# . ensure both variables are unset for typical builds
13+
#
14+
# building:
15+
# make build-image . run docker build
16+
# make build-push . push image to repository
17+
# make image . build + push
18+
#
19+
# Stages:
20+
# runtime <- debian-base-amd64:0.2
21+
# common runtime packages go here
22+
# build-setup <- runtime
23+
# dev packages, tools, utilities, etc. go here
24+
# builder <- build-setup
25+
# ./configure <things> && make && make install
26+
# post-build <- builder
27+
# install any common python modules here
28+
# FINAL <- runtime
29+
# pip package installation goes here + ENTRYPOINT
30+
#
31+
###############################################################################
32+
33+
FROM gcr.io/google-containers/debian-base-amd64:0.2 as runtime
34+
35+
ENV PATH /usr/local/bin:$PATH
36+
37+
# http://bugs.python.org/issue19846
38+
# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
39+
40+
ENV LANG C.UTF-8
41+
42+
COPY ./init-functions /lib/lsb/
43+
44+
RUN set -ex \
45+
&& apt-mark unhold apt gnupg libcap2 libsemanage1 passwd libbz2-1.0\
46+
&& runDeps='curl gnupg libsqlite3-0 zlib1g libexpat1 bash tcpdump procps less binutils libbz2-1.0 netcat-openbsd' \
47+
&& apt-get -qq update; apt-get install -y $runDeps \
48+
&& find /usr -type f -name "*.so" -exec strip --strip-unneeded {} + \
49+
&& apt-get remove binutils --purge -y -qq \
50+
&& find /var/lib/apt/lists \
51+
/usr/share/man \
52+
/usr/share/doc \
53+
/var/log \
54+
-type f -exec rm -f {} + \
55+
&& rm -rf /root/.gnupg \
56+
&& mkdir -p /root/.gnupg \
57+
&& chmod 700 /root/.gnupg
58+
59+
LABEL stage RUNTIME
60+
61+
###############################################################################
62+
FROM runtime as build-setup
63+
64+
ADD gnupg/pubring.gpg gnupg/trustdb.gpg /root/.gnupg/
65+
66+
RUN set -ex \
67+
&& mkdir -p /root/.gnupg \
68+
&& chmod 700 /root/.gnupg \
69+
&& buildDeps='libsqlite3-dev zlib1g-dev libexpat1-dev libssl-dev xz-utils dpkg-dev binutils libbz2-dev libreadline-dev' \
70+
&& apt-get -qq update; apt-get -qq -y install ${buildDeps}
71+
72+
ARG PYTHON_VERSION
73+
74+
RUN curl -L -o /python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \
75+
&& curl -L -o /python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \
76+
&& gpg --keyserver ha.pool.sks-keyservers.net --refresh-keys 2>&1 | egrep -v 'requesting key|not changed' \
77+
&& gpg --batch --verify /python.tar.xz.asc /python.tar.xz \
78+
&& mkdir -p /usr/src/python \
79+
&& tar -xJC /usr/src/python --strip-components=1 -f /python.tar.xz
80+
81+
82+
LABEL stage BUILD-SETUP
83+
LABEL version ${PYTHON_VERSION}
84+
85+
###############################################################################
86+
FROM build-setup as builder
87+
88+
ARG BUILD_ARGS
89+
ARG PYTHON_VERSION
90+
ENV LANG C.UTF-8
91+
92+
RUN set -ex \
93+
&& cd /usr/src/python \
94+
&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
95+
&& [ $(( ` echo $PYTHON_VERSION | cut -d"." -f1 ` )) -lt 3 ] && BUILD_ARGS="" \
96+
; ./configure \
97+
--build="$gnuArch" \
98+
--enable-loadable-sqlite-extensions \
99+
--enable-shared \
100+
--with-system-expat \
101+
--with-system-ffi \
102+
--without-ensurepip ${BUILD_ARGS} \
103+
&& make -j $(( 1 * $( egrep '^processor[[:space:]]+:' /proc/cpuinfo | wc -l ) )) \
104+
&& make install
105+
106+
RUN set -ex \
107+
find /usr/local -type f -name "*.so" -exec strip --strip-unneeded {} + \
108+
& ldconfig \
109+
& find /usr/local -depth \
110+
\( \
111+
\( -type d -a \( -name test -o -name tests -o -name __pycache__ \) \) \
112+
-o \
113+
\( -type f -a \( -name '*.pyc' -o -name '*.pyo' \) \) \
114+
-o \
115+
\( -name "idle*" \) \
116+
\) -exec rm -rf '{}' + \
117+
&& find /var/lib/apt/lists \
118+
/usr/share/man \
119+
/usr/share/doc \
120+
/var/log \
121+
-type f -exec rm -f {} +
122+
123+
# make some useful symlinks that are expected to exist
124+
RUN ["/bin/bash", "-c", "if [[ $( echo ${PYTHON_VERSION} | cut -d'.' -f1 ) == '3' ]]; then cd /usr/local/bin && ln -sf pydoc3 pydoc && ln -sf python3 python && ln -sf python3-config python-config; fi"]
125+
126+
LABEL stage BUILDER
127+
LABEL version ${PYTHON_VERSION}
128+
129+
###############################################################################
130+
FROM builder as post-build
131+
132+
# if this is called "PIP_VERSION", pip explodes with "ValueError: invalid truth value '<VERSION>'"
133+
ENV PYTHON_PIP_VERSION 9.0.1
134+
135+
136+
COPY ./ipython_config.py /
137+
138+
RUN set -ex; ldconfig
139+
RUN set -ex; curl -sL -o get-pip.py 'https://bootstrap.pypa.io/get-pip.py';
140+
RUN set -ex; python get-pip.py \
141+
--disable-pip-version-check \
142+
--no-cache-dir \
143+
"pip==$PYTHON_PIP_VERSION"; pip --version
144+
145+
RUN mkdir -p $HOME/.ipython/profile_default ;
146+
RUN mv ipython_config.py $HOME/.ipython/profile_default/. ;
147+
RUN pip install 'ipython<6' ipdb
148+
149+
RUN set -ex; \
150+
find /usr/local -depth \
151+
\( \
152+
\( -type d -a \( -name test -o -name tests -o -name __pycache__ \) \) \
153+
-o \
154+
\( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name '*.exe' \) \) \
155+
\) -exec rm -rf '{}' +;
156+
157+
ARG PYTHON_VERSION
158+
LABEL stage POST-BUILD
159+
LABEL version ${PYTHON_VERSION}
160+
161+
###############################################################################
162+
FROM runtime
163+
164+
COPY --from=post-build /usr/local /usr/local
165+
COPY --from=post-build /root /root
166+
RUN /sbin/ldconfig
167+
168+
LABEL stage FINAL
169+
ARG PYTHON_VERSION
170+
LABEL version ${PYTHON_VERSION}
171+
172+
CMD ["ipython"]

Makefile

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.PHONY: image push-image build-image optimal
2+
3+
include .version
4+
5+
PYTHON_VERSION ?= 3.6.2
6+
FUCKOFF = ${MAJOR_VERSION}
7+
8+
TAG = ${PYTHON_VERSION}-wee
9+
10+
IMAGE_TAG = ${IMAGE}:${TAG}
11+
12+
BUILD_ARGS =
13+
14+
15+
ifdef PKG_PROXY
16+
PROXY_ARGS := --build-arg=http_proxy=${PKG_PROXY} --build-arg=https_proxy=${PKG_PROXY}
17+
else
18+
PROXY_ARGS :=
19+
endif
20+
21+
ifdef PIP_PROXY_HOST
22+
PIP_PROXY_ARGS := --add-host=pypi.python.org=${PIP_PROXY_HOST}
23+
else
24+
PIP_PROXY_ARGS :=
25+
endif
26+
27+
28+
ifdef OPTIMAL
29+
BUILD_ARGS += --enable-optimizations
30+
TAG := ${TAG}-optimized
31+
endif
32+
33+
ifdef LTO
34+
BUILD_ARGS += --with-lto
35+
TAG := ${TAG}-lto
36+
endif
37+
38+
39+
build-image:
40+
@echo building ${IMAGE_TAG}
41+
@docker build ${PROXY_ARGS} --build-arg=PYTHON_VERSION=${PYTHON_VERSION} --build-arg=BUILD_ARGS="${BUILD_ARGS}" -t ${IMAGE_TAG} --compress .
42+
43+
push-image:
44+
@echo pushing ${IMAGE_TAG}
45+
@docker push ${IMAGE_TAG}
46+
47+
image: build-image push-image

README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
2+
# RevSys Python Builds
3+
4+
*NOTE*: This README isn't 100% accurate and up to date, we will fix it in the near future. Busy at a conference this weekend.
5+
6+
## What’s wrong with stock Python images?
7+
8+
The main image variety is too big when the user is operating in a context
9+
that involves multiple private registries.
10+
11+
It’s base layer is an Ubuntu image (with a few exceptions, this
12+
provides an as-installed-by-Ubuntu environment) which is, essentially, what
13+
one gets with a base minimal install of Ubuntu 16.04.
14+
15+
The [alpine](https://alpinelinux.org/) images are delightfully wee. But, alas,
16+
[musl](https://www.musl-libc.org/). It is awesome. I mean, it *exists*. If you
17+
don’t have build problems with your modules that have a C or C++ component,
18+
use it. It is small, fast and well vetted.
19+
20+
**Note**: There are workarounds for *some* of the more common non-pure-python
21+
module build failures but usually involve much shenaniganry that I have neither the time
22+
nor inclination to pursue.
23+
24+
The **slim** images are similar to the ubuntu images. Rather than an Ubuntu base
25+
image, they use a Debian 8 base.
26+
27+
| REPOSITORY | TAG | SIZE |
28+
| ----------- | ---------------------- | ----- |
29+
| python | 3.6.3 | 690MB |
30+
| python | 3.6-slim | 201MB |
31+
| python | 3.6.3-alpine | 89MB |
32+
| registry.gitlab.com/revsys/docker-builds/python | 3.6.3-wee | 153MB |
33+
34+
We settled on a Debian 8 image provided by google’s GCE service. It is smaller
35+
by way of excluding systemd-related bits while building the initial bootstrap
36+
chroot.
37+
38+
The resulting images are smaller than -slim but larger than alpine.
39+
40+
## Optimized Python images
41+
42+
Three builds are available per Python version:
43+
44+
* :wee - stock build without compile or link-time optimizations enabled
45+
* :wee-optimized - build with profile-guided optimization flag
46+
* :wee-optimized-lto - build with PGO + Link-Time-Optimization flags
47+
48+
49+
| REPOSITORY | TAG | SIZE |
50+
| ----------- | ---------------------- | ----- |
51+
| revolutionsystems/python | 3.5.3-wee-optimized-lto | 164MB |
52+
| revolutionsystems/python | 3.5.3-wee-optimized | 164MB |
53+
| revolutionsystems/python | 3.5.3-wee | 158MB |
54+
55+
## Building
56+
57+
The registry is included from <gitroot>/.versions
58+
59+
make targets:
60+
61+
* build-image: docker build...
62+
* push-image: docker push ...
63+
* image: runs build-image then push-image
64+
65+
### stock build
66+
67+
```
68+
69+
:# LTO= OPTIMAL= PYTHON_VERSION=3.5.3 make image
70+
71+
```
72+
73+
### PGO optimizations
74+
75+
```
76+
77+
:# LTO= OPTIMAL=1 PYTHON_VERSION=3.5.1 make image
78+
79+
```
80+
81+
### LTO Optimizations
82+
83+
```
84+
85+
:# LTO=1 OPTIMAL=1 PYTHON_VERSION=3.6.3 make image
86+
87+
```
88+
89+
### Python 2 builds
90+
91+
The build arguments have stayed fairly consistent at least since Python 2.6.
92+
The build will not fail if the Python 3-specific environment variables remain
93+
set; however, the image will get a misleading tag. For Python 2 builds, use:
94+
95+
```
96+
97+
:# LTO= OPTIMAL= PYTHON_VERSION=2.7.13 make image
98+
99+
```
100+
101+
## Build Optimization
102+
103+
Build times are radically reduced by using a local proxy. You can find an
104+
example squid 3/4 configuration in ./examples.
105+
106+
After setting the `cache_dir` path the command, `squid -f /path/to/config -N -z`
107+
to initialize the cache filesystem storage.
108+
109+
To kick off the cache service: `squid -f /path/to/config -N -a 3128`.
110+
111+
Once the proxy is running, set the environment variable `export PKG_PROXY=http://10.129.1.1:3128`.
112+
Docker transparently passes the `HTTP_PROXY` and `HTTPS_PROXY` environment variables
113+
into each build container if they are configured with the `--build-args` flag.
114+
115+
The transparency is significant in that whether or not your build is leveraging
116+
a proxy will not affect the validity of the build host’s cache.

benchmarks/3.5.4/py354_lto_pgo.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

benchmarks/3.5.4/py354_nonopt.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

benchmarks/3.6.3/python3.6.3-optimized_0.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

benchmarks/3.6.3/python3.6.3-optimized_2.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

benchmarks/3.6.3/python3.6.3-optimized_3.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

benchmarks/3.6.3/python3.6.3-optimized_4.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

benchmarks/3.6.3/python3.6.3-optimized_5.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy