Skip to content

Commit

Permalink
docker/perl_dzil (#3)
Browse files Browse the repository at this point in the history
* Add dzil recipe

This also serves as a very simple example of using our base perl image.

* Dockerfile: a couple more fixes

- Check aptfile for readability, not size, so it can be skipped if the
 file doesn't exist.

- Do not auto-remove removable packages; removing them doesn't affect
  the overall image size anyway, and some packages (like runtime libraries
  auto-installed by their -dev counterparts) can be inadventently
  removed and break CPAN modules.

* .github/workflows/test.yaml: Test dzil image as well

This probably needs its own workflow later, but for now just do a quick
build and check using the dzil image.

* Dockerfile: invoke dumb-init on cpanm ONBUILD for signals handling

This is important for cross-compile builds (e.g. amd64 to arm64) as
cpanm/perl won't handle signals without defining them in the code, cf
Perl/docker-perl#44.  Without this,
cross-compiles will appear to stall.

* Move apt/cpan setup to script so we can call in sub-images too

* dzil build should pull in authordeps and apply Pod::Inherit patch for the DERIV author bundle

* Include Pod::Inherit @inc patch

* Include CircleCI config as well

* Update CircleCI docker orb

* Latest orb does not have artifacts path for hadolint

* List of dockerfiles now colon-separated

* Switch to orb versions of build+publish

* Clean up CircleCI config - no point running hadolint everywhere

* Apply hadolint recommendations

* Filter out some more hadolint checks

* Try to set WORKDIR

* Attempt to make job steps sequential

* Apply `perl` context

* CircleCI orb has several bugs, so the current version is not usable

* Report $DOCKER_LOGIN to test context-is-broken hypothesis

Co-authored-by: Zak B. Elep <[email protected]>
  • Loading branch information
tom-binary and zakame authored Aug 23, 2020
1 parent e002a31 commit 10c8e8e
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 28 deletions.
96 changes: 96 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
version: 2.1
orbs:
docker: circleci/[email protected]
jobs:
perl:
executor: docker/docker
steps:
- setup_remote_docker
- checkout
- run:
command: |
echo Log in as "$DOCKER_LOGIN"
echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_LOGIN" --password-stdin
docker build -t deriv/perl .
name: Build deriv/perl
dzil:
executor: docker/docker
steps:
- setup_remote_docker
- checkout
- run:
command: |
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_LOGIN" --password-stdin
cd dzil && docker build -t deriv/dzil .
name: Build deriv/dzil
workflows:
version: 2
build-workflow:
jobs:
- perl:
context: perl
- dzil:
context: perl
requires:
- perl
- docker/hadolint:
dockerfiles: Dockerfile:dzil/Dockerfile
# Don't pin apt versions, we'll never remember to update them
ignore-rules: DL3008,SC2046,DL3003,DL4006,DL3006
merged:
jobs:
- docker/publish:
deploy: true
image: deriv/perl
filters:
branches:
only: /^master$/
- docker/publish:
deploy: true
image: deriv/dzil
path: dzil
filters:
branches:
only: /^master$/
- docker/hadolint:
dockerfiles: Dockerfile:dzil/Dockerfile
# Don't pin apt versions, we'll never remember to update them
ignore-rules: DL3008,SC2046,DL3003,DL4006,DL3006
filters:
branches:
only: /^master$/
tagged:
jobs:
- docker/publish:
deploy: true
image: deriv/perl
filters:
branches:
only: /^master$/
- docker/publish:
deploy: true
image: deriv/dzil
path: dzil
filters:
branches:
only: /^master$/
daily:
jobs:
- docker/publish:
deploy: false
image: deriv/perl
- docker/publish:
deploy: false
image: deriv/dzil
path: dzil
- docker/hadolint:
dockerfiles: Dockerfile:dzil/Dockerfile
# Don't pin apt versions, we'll never remember to update them
ignore-rules: DL3008,SC2046,DL3003,DL4006,DL3006
triggers:
- schedule:
cron: 05 19 * * *
filters:
branches:
only:
- master
7 changes: 5 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build image
name: Build images

on:
push:
Expand All @@ -13,12 +13,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Build base perl image
- name: Build images
run: |
docker version
[ -n $DEBIAN_PROXY ] && docker_build_opts="--build-arg=DEBIAN_PROXY=${DEBIAN_PROXY}"
docker build "$docker_build_opts" -t deriv/perl .
cd dzil && docker build "$docker_build_opts" -t deriv/dzil .
- name: Inspect image creation and tag time
run: |
docker image inspect --format \'{{.Created}}\' deriv/perl
docker image inspect --format \'{{.Metadata.LastTagTime}}\' deriv/perl
docker image inspect --format \'{{.Created}}\' deriv/dzil
docker image inspect --format \'{{.Metadata.LastTagTime}}\' deriv/dzil
43 changes: 17 additions & 26 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,60 +12,51 @@ ENV CPANM_SHA256=9b60767fe40752ef7a9d3f13f19060a63389a5c23acc3e9827e19b75500f81f

# Use an apt-cacher-ng or similar proxy when available during builds
ARG DEBIAN_PROXY
ARG HTTP_PROXY

WORKDIR /usr/src/perl

RUN [ -n "$DEBIAN_PROXY" ] \
&& (echo "Acquire::http::Proxy \"http://$DEBIAN_PROXY\";" > /etc/apt/apt.conf.d/30proxy) \
&& (echo "Acquire::http::Proxy::ppa.launchpad.net DIRECT;" >> /etc/apt/apt.conf.d/30proxy) \
|| echo "No local Debian proxy configured" \
&& apt-get update \
&& apt-get dist-upgrade -y -q --no-install-recommends \
&& apt-get install -y -q --no-install-recommends \
git openssh-client curl socat ca-certificates gcc make libc6-dev libssl-dev zlib1g-dev xz-utils dumb-init \
&& curl -SL https://www.cpan.org/src/5.0/perl-${PERL_VERSION}.tar.xz -o perl-${PERL_VERSION}.tar.xz \
git openssh-client curl socat ca-certificates gcc make libc6-dev libssl-dev zlib1g-dev xz-utils dumb-init patch \
&& curl -SL https://www.cpan.org/src/5.0/"perl-${PERL_VERSION}".tar.xz -o "perl-${PERL_VERSION}".tar.xz \
&& echo "${PERL_SHA256} *perl-${PERL_VERSION}.tar.xz" | sha256sum -c - \
&& tar --strip-components=1 -xaf perl-${PERL_VERSION}.tar.xz -C /usr/src/perl \
&& rm perl-${PERL_VERSION}.tar.xz \
&& ./Configure -Duse64bitall -Duseshrplib -Dprefix=/opt/perl-${PERL_VERSION} -Dman1dir=none -Dman3dir=none -des \
&& tar --strip-components=1 -xaf "perl-${PERL_VERSION}".tar.xz -C /usr/src/perl \
&& rm "perl-${PERL_VERSION}".tar.xz \
&& ./Configure -Duse64bitall -Duseshrplib -Dprefix=/opt/"perl-${PERL_VERSION}" -Dman1dir=none -Dman3dir=none -des \
&& make -j$(nproc) \
&& make install \
&& cd /usr/src \
&& curl -LO https://www.cpan.org/authors/id/M/MI/MIYAGAWA/App-cpanminus-${CPANM_VERSION}.tar.gz \
&& echo "${CPANM_SHA256} *App-cpanminus-${CPANM_VERSION}.tar.gz" | sha256sum -c - \
&& tar -xzf App-cpanminus-${CPANM_VERSION}.tar.gz \
&& rm App-cpanminus-${CPANM_VERSION}.tar.gz \
&& cd App-cpanminus-${CPANM_VERSION} && /opt/perl-${PERL_VERSION}/bin/perl bin/cpanm . \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
&& rm -fr ./cpanm /root/.cpanm /usr/src/perl /usr/src/App-cpanminus-${CPANM_VERSION}* /tmp/* \
# Locale support is probably quite useful in some cases, but
# let's let individual builds decide that via aptfile config
# && echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen \
# && locale-gen \
&& tar -xzf "App-cpanminus-${CPANM_VERSION}".tar.gz \
&& rm "App-cpanminus-${CPANM_VERSION}".tar.gz \
&& cd "App-cpanminus-${CPANM_VERSION}" && /opt/"perl-${PERL_VERSION}"/bin/perl bin/cpanm . \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/* /etc/apt/apt.conf.d/30proxy \
&& rm -fr ./cpanm /root/.cpanm /usr/src/perl /usr/src/"App-cpanminus-${CPANM_VERSION}"* /tmp/* \
&& mkdir -p /etc/ssh/ \
&& ssh-keyscan github.com >> /etc/ssh/ssh_known_hosts \
&& mkdir -p /app

WORKDIR /app/
COPY prepare-apt-cpan.sh /usr/local/bin/

ENV PATH="/opt/perl-${PERL_VERSION}/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin"

ONBUILD ADD cpanfile aptfile /app/
ONBUILD ARG HTTP_PROXY
ONBUILD WORKDIR /app/
ONBUILD COPY cpanfile aptfile /app/

# Install everything in the aptfile first, as system deps, then
# go through the CPAN deps. Once those are all done, remove anything
# that we would have pulled in as a build dep (compilers, for example)
# unless they happened to be in the aptfile.
ONBUILD RUN if [ -s /app/aptfile ]; then \
apt-get -y -q update \
&& apt-get -y -q --no-install-recommends install $(cat /app/aptfile); \
fi \
&& cpanm --notest --quiet --installdeps --with-recommends . \
&& apt-get purge -y -q $(perl -le'@seen{split " ", "" . do { local ($/, @ARGV) = (undef, "/app/aptfile"); <> }} = () if -r "aptfile"; print for grep { !exists $seen{$_} } qw(make gcc git openssh-client libc6-dev libssl-dev zlib1g-dev)') \
&& apt-get -y --purge autoremove \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/* /root/.cpanm /tmp/*

ONBUILD ADD . /app/
ONBUILD RUN prepare-apt-cpan.sh
ONBUILD COPY . /app/

ENTRYPOINT [ "/usr/bin/dumb-init", "--" ]

Expand Down
8 changes: 8 additions & 0 deletions dzil/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ARG HTTP_PROXY
FROM deriv/perl
COPY pod-inherit.patch .
RUN patch -p0 $(perldoc -lm Pod::Inherit) < pod-inherit.patch
ONBUILD COPY cpanfile aptfile dist.ini /app/
ONBUILD RUN prepare-apt-cpan.sh \
&& dzil authordeps | cpanm -n
ONBUILD COPY . /app/
8 changes: 8 additions & 0 deletions dzil/aptfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
libncurses-dev
libreadline-dev
git
gcc
make
libc6-dev
openssh-client
patch
1 change: 1 addition & 0 deletions dzil/cpanfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requires 'Dist::Zilla::PluginBundle::Author::DERIV';
22 changes: 22 additions & 0 deletions dzil/pod-inherit.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--- a/Pod/Inherit.pm 2020-04-03 21:58:36.470197738 +0800
+++ b/Pod/Inherit.pm 2014-06-13 10:45:18.000000000 +0800
@@ -909,7 +909,7 @@
unless (exists $INC{$class_as_filename}) {
# Still no source? Great... we'll have to pray that require will work...
print "Still no source found for $classname; forced to use 'require'\n" if ($DEBUG && !$src);
- my $did_it = $src ? do $src : Class::Load::load_optional_class($classname);
+ my $did_it = $src ? do "./$src" : Class::Load::load_optional_class($classname);
unless ($did_it) {
my $err = $@;
$err =~ s/ \(\@INC contains: .*\)//;
@@ -994,7 +994,10 @@
$src = Path::Class::File->new($src)->as_foreign('Unix');

return <<__END_HEADER__;
+=encoding utf8
+
=for comment POD_DERIVED_INDEX_GENERATED
+
The following documentation is automatically generated. Please do not edit
this file, but rather the original, inline with $classname
at $src
14 changes: 14 additions & 0 deletions prepare-apt-cpan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
# Prepare dependencies by installing anything found in `aptfile`
# then applying CPAN modules from `cpanfile`.

set -e

if [ -r /app/aptfile ]; then
apt-get -y -q update
apt-get -y -q --no-install-recommends install $(cat /app/aptfile)
fi
cpanm --notest --installdeps .
apt-get purge -y -q $(perl -le'@seen{split " ", "" . do { local ($/, @ARGV) = (undef, "/app/aptfile"); <> }} = () if -r "aptfile"; print for grep { !exists $seen{$_} } qw(make gcc git openssh-client libc6-dev libssl-dev zlib1g-dev patch)')
rm -rf /var/lib/apt/lists/* /var/cache/apt/* /root/.cpanm /tmp/*

0 comments on commit 10c8e8e

Please sign in to comment.