Skip to content

Commit

Permalink
Change Dockerfile to be a multistage build
Browse files Browse the repository at this point in the history
The existing Dockerfile produced a broken binary (static
compile caused the binary to segfault).

This patch changes the Dockerfile to

- Build a non-static binary
- Use a multi-stage build: separate stages are used for build and
  deploy; the build stage contains the tools needed for building
  the binary, after which the build artefacts are copied to the
  final stage. which produces the actual image.
  Using this approach, the build-tools can be kept in the Docker
  build-cache, which improves performance of repeated builds and
  does not require cleanup steps in the Dockerfile itself, which
  can simplify the steps.
- The official Python image is used for the build stage, so that
  there is no need to install python manually. The version of python
  is set to the same version as the version used in CI, but can be
  overridden using at build-time using a build-arg:

    docker build --build-arg PYTHON_VERSION=x ..

- Both build- and deploy stages use the debian "stretch" variants,
  which matches what's used in the current version of the Dockerfile,
  but could be updated to the current stable ("buster") variant if
  there is a need.
- The final stage uses the "slim" variant to reduce the size. For
  comparison, below are sizes of the final image when using the
  regular, or "slim" version of the image:

    REPOSITORY  TAG                 IMAGE ID            CREATED             SIZE
    jq          stretch-slim        4b7f380970f0        About a minute ago  70.3MB
    jq          stretch             c5fa8b766cd4        7 minutes ago       119MB

A .dockerignore file is also added to prevent "busting" the Docker
build-cache if not needed, and steps in the Dockerfile are optimized
for BuildKit, but remain compatible with the legacy builder. To build,
and verify the image:

    DOCKER_BUILDKIT=1 docker build -t jq .

And, test the image, us it (for example) to pretty-print its own
"docker image inspect" output:

    docker image inspect jq | docker run -i --rm jq .
    [
      {
        "Id": "sha256:4b7f380970f0d06d4ca9137fbbb3fa3f6554da996147d1d956cda6f44be25650",
        "RepoTags": [
          "jq:latest",
          "jq:stretch-slim"
        ],

Signed-off-by: Sebastiaan van Stijn <[email protected]>
  • Loading branch information
thaJeztah committed Nov 1, 2019
1 parent bda75c3 commit e23ca59
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 46 deletions.
61 changes: 61 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
*.o
*.a
*.lo
*.la
*.lai
*.so
*.so.*
*.gcda
*.gcno
*.gcov
*~
.*.sw[a-p]
tags

jq
!tests/modules/lib/jq/
jq.1

# Generated source
src/builtin.inc
*.pc

# Autotools junk
.libs
.deps
.dirstamp
libtool
*.log
stamp-h1
config.log
config.status
autom4te.cache
INSTALL
Makefile
jq-*.tar.gz
configure
aclocal.m4
Makefile.in
version.h
.remake-version-h
config.cache
*.rpm
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
tests/*.trs

cscope.in.out
cscope.out
cscope.po.out
jq.dSYM

# Don't bust the build-cache on Dockerfile/.dockerignore only changes
.dockerignore
.github
.travis.yml
appveyor.yml
build/*
docs
92 changes: 46 additions & 46 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
FROM debian:9

ENV DEBIAN_FRONTEND=noninteractive \
DEBCONF_NONINTERACTIVE_SEEN=true \
LC_ALL=C.UTF-8 \
LANG=C.UTF-8
ARG PYTHON_VERSION=3.6.7

COPY . /app

# get dependencies, build, and remove anything we don't need for running jq.
# valgrind seems to have trouble with pthreads TLS so it's off.

RUN apt-get update && \
apt-get install -y \
build-essential \
FROM python:${PYTHON_VERSION}-stretch AS build
CMD ["bash"]
ENV LC_ALL=C.UTF-8
ARG DEBIAN_FRONTEND=noninteractive
ARG DEBCONF_NONINTERACTIVE_SEEN=true
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
autoconf \
libtool \
git \
bison \
flex \
python3 \
python3-pip \
wget && \
pip3 install pipenv && \
(cd /app/docs && pipenv sync) && \
(cd /app && \
git submodule init && \
git submodule update && \
autoreconf -i && \
./configure --disable-valgrind --enable-all-static --prefix=/usr/local && \
make -j8 && \
make check && \
make install ) && \
(cd /app/modules/oniguruma && \
make uninstall ) && \
(cd /app && \
make distclean ) && \
apt-get purge -y \
build-essential \
autoconf \
libtool \
bison \
git \
flex \
python3 \
python3-pip && \
apt-get autoremove -y && \
rm -rf /app/modules/oniguruma/* && \
rm -rf /app/modules/oniguruma/.git && \
rm -rf /app/modules/oniguruma/.gitignore && \
rm -rf /var/lib/apt/lists/* /var/lib/gems
git \
libtool \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install docs dependencies; we're only copying the Pipfile here,
# so that this is only run again if dependencies change
RUN pip3 install pipenv
COPY docs/Pipfile docs/Pipfile.lock ./docs/
RUN cd docs && pipenv sync

COPY .gitmodules .
COPY .git ./.git/
RUN git submodule init
RUN git submodule update
RUN sed -i.bak '/^AM_INIT_AUTOMAKE(\[-Wno-portability 1\.14\])$/s/14/11/' modules/oniguruma/configure.ac

COPY . .
RUN autoreconf -if
RUN ./configure --disable-valgrind --with-oniguruma=builtin YACC=/usr/bin/bison --prefix=/build/
RUN make BISON_PKGDATADIR=/usr/bin/bison src/parser.c || make src/parser.c
RUN make -j8
RUN make check -j8
RUN make install
RUN /build/bin/jq -V

# Collect the files for the final image
FROM debian:stretch-slim AS deploy
ENV LC_ALL=C.UTF-8
ARG DEBIAN_FRONTEND=noninteractive
ARG DEBCONF_NONINTERACTIVE_SEEN=true
RUN apt-get update \
&& apt-get install -y --no-install-recommends man \
&& rm -rf /var/lib/apt/lists/*

COPY --from=build /build/. /usr/local/
RUN jq -V
ENTRYPOINT ["/usr/local/bin/jq"]
CMD []
CMD ["--help"]

0 comments on commit e23ca59

Please sign in to comment.