Skip to content

Commit 56a20ba

Browse files
committed
Added update script and template to make changes management easier
1 parent 4a6623a commit 56a20ba

File tree

6 files changed

+498
-0
lines changed

6 files changed

+498
-0
lines changed

Dockerfile-alpine.template

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
FROM alpine:%%ALPINE_VERSION%%
2+
3+
LABEL maintainer="NGINX Docker Maintainers <[email protected]>"
4+
5+
ENV NGINX_VERSION %%NGINX_VERSION%%
6+
ENV NJS_VERSION %%NJS_VERSION%%
7+
ENV PKG_RELEASE %%PKG_RELEASE%%
8+
9+
RUN set -x \
10+
# create nginx user/group first, to be consistent throughout docker variants
11+
&& addgroup -g 101 -S nginx \
12+
&& adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \
13+
&& apkArch="$(cat /etc/apk/arch)" \
14+
&& nginxPackages="%%PACKAGES%%
15+
" \
16+
&& case "$apkArch" in \
17+
x86_64) \
18+
# arches officially built by upstream
19+
set -x \
20+
&& KEY_SHA512="e7fa8303923d9b95db37a77ad46c68fd4755ff935d0a534d26eba83de193c76166c68bfe7f65471bf8881004ef4aa6df3e34689c305662750c0172fca5d8552a *stdin" \
21+
&& apk add --no-cache --virtual .cert-deps \
22+
openssl \
23+
&& wget -O /tmp/nginx_signing.rsa.pub https://nginx.org/keys/nginx_signing.rsa.pub \
24+
&& if [ "$(openssl rsa -pubin -in /tmp/nginx_signing.rsa.pub -text -noout | openssl sha512 -r)" = "$KEY_SHA512" ]; then \
25+
echo "key verification succeeded!"; \
26+
mv /tmp/nginx_signing.rsa.pub /etc/apk/keys/; \
27+
else \
28+
echo "key verification failed!"; \
29+
exit 1; \
30+
fi \
31+
&& apk del .cert-deps \
32+
&& apk add -X "%%PACKAGEREPO%%v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" --no-cache $nginxPackages \
33+
;; \
34+
*) \
35+
# we're on an architecture upstream doesn't officially build for
36+
# let's build binaries from the published packaging sources
37+
set -x \
38+
&& tempDir="$(mktemp -d)" \
39+
&& chown nobody:nobody $tempDir \
40+
&& apk add --no-cache --virtual .build-deps \
41+
gcc \
42+
libc-dev \
43+
make \
44+
openssl-dev \
45+
pcre-dev \
46+
zlib-dev \
47+
linux-headers \
48+
libxslt-dev \
49+
gd-dev \
50+
geoip-dev \
51+
perl-dev \
52+
libedit-dev \
53+
mercurial \
54+
bash \
55+
alpine-sdk \
56+
findutils \
57+
&& su nobody -s /bin/sh -c " \
58+
export HOME=${tempDir} \
59+
&& cd ${tempDir} \
60+
&& hg clone https://hg.nginx.org/pkg-oss \
61+
&& cd pkg-oss \
62+
&& hg up %%REVISION%% \
63+
&& cd alpine \
64+
&& make all \
65+
&& apk index -o ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz ${tempDir}/packages/alpine/${apkArch}/*.apk \
66+
&& abuild-sign -k ${tempDir}/.abuild/abuild-key.rsa ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz \
67+
" \
68+
&& cp ${tempDir}/.abuild/abuild-key.rsa.pub /etc/apk/keys/ \
69+
&& apk del .build-deps \
70+
&& apk add -X ${tempDir}/packages/alpine/ --no-cache $nginxPackages \
71+
;; \
72+
esac \
73+
# if we have leftovers from building, let's purge them (including extra, unnecessary build deps)
74+
&& if [ -n "$tempDir" ]; then rm -rf "$tempDir"; fi \
75+
&& if [ -n "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi \
76+
&& if [ -n "/etc/apk/keys/nginx_signing.rsa.pub" ]; then rm -f /etc/apk/keys/nginx_signing.rsa.pub; fi \
77+
# Bring in gettext so we can get `envsubst`, then throw
78+
# the rest away. To do this, we need to install `gettext`
79+
# then move `envsubst` out of the way so `gettext` can
80+
# be deleted completely, then move `envsubst` back.
81+
&& apk add --no-cache --virtual .gettext gettext \
82+
&& mv /usr/bin/envsubst /tmp/ \
83+
\
84+
&& runDeps="$( \
85+
scanelf --needed --nobanner /tmp/envsubst \
86+
| awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
87+
| sort -u \
88+
| xargs -r apk info --installed \
89+
| sort -u \
90+
)" \
91+
&& apk add --no-cache $runDeps \
92+
&& apk del .gettext \
93+
&& mv /tmp/envsubst /usr/local/bin/ \
94+
# Bring in tzdata so users could set the timezones through the environment
95+
# variables
96+
&& apk add --no-cache tzdata \
97+
# Bring in curl and ca-certificates to make registering on DNS SD easier
98+
&& apk add --no-cache curl ca-certificates \
99+
# forward request and error logs to docker log collector
100+
&& ln -sf /dev/stdout /var/log/nginx/access.log \
101+
&& ln -sf /dev/stderr /var/log/nginx/error.log \
102+
# create a docker-entrypoint.d directory
103+
&& mkdir /docker-entrypoint.d
104+
105+
COPY docker-entrypoint.sh /
106+
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
107+
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
108+
ENTRYPOINT ["/docker-entrypoint.sh"]
109+
110+
EXPOSE 80
111+
112+
STOPSIGNAL SIGTERM
113+
114+
CMD ["nginx", "-g", "daemon off;"]

Dockerfile-debian.template

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
FROM debian:%%DEBIAN_VERSION%%-slim
2+
3+
LABEL maintainer="NGINX Docker Maintainers <[email protected]>"
4+
5+
ENV NGINX_VERSION %%NGINX_VERSION%%
6+
ENV NJS_VERSION %%NJS_VERSION%%
7+
ENV PKG_RELEASE %%PKG_RELEASE%%
8+
9+
RUN set -x \
10+
# create nginx user/group first, to be consistent throughout docker variants
11+
&& addgroup --system --gid 101 nginx \
12+
&& adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx \
13+
&& apt-get update \
14+
&& apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates \
15+
&& \
16+
NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
17+
found=''; \
18+
for server in \
19+
ha.pool.sks-keyservers.net \
20+
hkp://keyserver.ubuntu.com:80 \
21+
hkp://p80.pool.sks-keyservers.net:80 \
22+
pgp.mit.edu \
23+
; do \
24+
echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
25+
apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
26+
done; \
27+
test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
28+
apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \
29+
&& dpkgArch="$(dpkg --print-architecture)" \
30+
&& nginxPackages="%%PACKAGES%%
31+
" \
32+
&& case "$dpkgArch" in \
33+
amd64|i386) \
34+
# arches officialy built by upstream
35+
echo "deb %%PACKAGEREPO%% %%DEBIAN_VERSION%% nginx" >> /etc/apt/sources.list.d/nginx.list \
36+
&& apt-get update \
37+
;; \
38+
*) \
39+
# we're on an architecture upstream doesn't officially build for
40+
# let's build binaries from the published source packages
41+
echo "deb-src %%PACKAGEREPO%% %%DEBIAN_VERSION%% nginx" >> /etc/apt/sources.list.d/nginx.list \
42+
\
43+
# new directory for storing sources and .deb files
44+
&& tempDir="$(mktemp -d)" \
45+
&& chmod 777 "$tempDir" \
46+
# (777 to ensure APT's "_apt" user can access it too)
47+
\
48+
# save list of currently-installed packages so build dependencies can be cleanly removed later
49+
&& savedAptMark="$(apt-mark showmanual)" \
50+
\
51+
# build .deb files from upstream's source packages (which are verified by apt-get)
52+
&& apt-get update \
53+
&& apt-get build-dep -y $nginxPackages \
54+
&& ( \
55+
cd "$tempDir" \
56+
&& DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" \
57+
apt-get source --compile $nginxPackages \
58+
) \
59+
# we don't remove APT lists here because they get re-downloaded and removed later
60+
\
61+
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
62+
# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies)
63+
&& apt-mark showmanual | xargs apt-mark auto > /dev/null \
64+
&& { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \
65+
\
66+
# create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be)
67+
&& ls -lAFh "$tempDir" \
68+
&& ( cd "$tempDir" && dpkg-scanpackages . > Packages ) \
69+
&& grep '^Package: ' "$tempDir/Packages" \
70+
&& echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \
71+
# work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes")
72+
# Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied)
73+
# ...
74+
# E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied)
75+
&& apt-get -o Acquire::GzipIndexes=false update \
76+
;; \
77+
esac \
78+
\
79+
&& apt-get install --no-install-recommends --no-install-suggests -y \
80+
$nginxPackages \
81+
gettext-base \
82+
curl \
83+
&& apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \
84+
\
85+
# if we have leftovers from building, let's purge them (including extra, unnecessary build deps)
86+
&& if [ -n "$tempDir" ]; then \
87+
apt-get purge -y --auto-remove \
88+
&& rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \
89+
fi \
90+
# forward request and error logs to docker log collector
91+
&& ln -sf /dev/stdout /var/log/nginx/access.log \
92+
&& ln -sf /dev/stderr /var/log/nginx/error.log \
93+
# create a docker-entrypoint.d directory
94+
&& mkdir /docker-entrypoint.d
95+
96+
COPY docker-entrypoint.sh /
97+
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
98+
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
99+
ENTRYPOINT ["/docker-entrypoint.sh"]
100+
101+
EXPOSE 80
102+
103+
STOPSIGNAL SIGTERM
104+
105+
CMD ["nginx", "-g", "daemon off;"]
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/sh
2+
# vim:sw=4:ts=4:et
3+
4+
set -e
5+
6+
ME=$(basename $0)
7+
DEFAULT_CONF_FILE="etc/nginx/conf.d/default.conf"
8+
9+
# check if we have ipv6 available
10+
if [ ! -f "/proc/net/if_inet6" ]; then
11+
echo >&3 "$ME: error: ipv6 not available"
12+
exit 0
13+
fi
14+
15+
if [ ! -f "/$DEFAULT_CONF_FILE" ]; then
16+
echo >&3 "$ME: error: /$DEFAULT_CONF_FILE is not a file or does not exist"
17+
exit 0
18+
fi
19+
20+
# check if the file can be modified, e.g. not on a r/o filesystem
21+
touch /$DEFAULT_CONF_FILE 2>/dev/null || { echo >&3 "$ME: error: can not modify /$DEFAULT_CONF_FILE (read-only file system?)"; exit 0; }
22+
23+
# check if the file is already modified, e.g. on a container restart
24+
grep -q "listen \[::]\:80;" /$DEFAULT_CONF_FILE && { echo >&3 "$ME: info: IPv6 listen already enabled"; exit 0; }
25+
26+
if [ -f "/etc/os-release" ]; then
27+
. /etc/os-release
28+
else
29+
echo >&3 "$ME: error: can not guess the operating system"
30+
exit 0
31+
fi
32+
33+
echo >&3 "$ME: Getting the checksum of /$DEFAULT_CONF_FILE"
34+
35+
case "$ID" in
36+
"debian")
37+
CHECKSUM=$(dpkg-query --show --showformat='${Conffiles}\n' nginx | grep $DEFAULT_CONF_FILE | cut -d' ' -f 3)
38+
echo "$CHECKSUM /$DEFAULT_CONF_FILE" | md5sum -c - >/dev/null 2>&1 || {
39+
echo >&3 "$ME: info: /$DEFAULT_CONF_FILE differs from the packaged version"
40+
exit 0
41+
}
42+
;;
43+
"alpine")
44+
CHECKSUM=$(apk manifest nginx 2>/dev/null| grep $DEFAULT_CONF_FILE | cut -d' ' -f 1 | cut -d ':' -f 2)
45+
echo "$CHECKSUM /$DEFAULT_CONF_FILE" | sha1sum -c - >/dev/null 2>&1 || {
46+
echo >&3 "$ME: info: /$DEFAULT_CONF_FILE differs from the packaged version"
47+
exit 0
48+
}
49+
;;
50+
*)
51+
echo >&3 "$ME: error: Unsupported distribution"
52+
exit 0
53+
;;
54+
esac
55+
56+
# enable ipv6 on default.conf listen sockets
57+
sed -i -E 's,listen 80;,listen 80;\n listen [::]:80;,' /$DEFAULT_CONF_FILE
58+
59+
echo >&3 "$ME: Enabled listen on IPv6 in /$DEFAULT_CONF_FILE"
60+
61+
exit 0
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/sh
2+
3+
set -e
4+
5+
ME=$(basename $0)
6+
7+
auto_envsubst() {
8+
local template_dir="${NGINX_ENVSUBST_TEMPLATE_DIR:-/etc/nginx/templates}"
9+
local suffix="${NGINX_ENVSUBST_TEMPLATE_SUFFIX:-.template}"
10+
local output_dir="${NGINX_ENVSUBST_OUTPUT_DIR:-/etc/nginx/conf.d}"
11+
12+
local template defined_envs relative_path output_path subdir
13+
defined_envs=$(printf '${%s} ' $(env | cut -d= -f1))
14+
[ -d "$template_dir" ] || return 0
15+
if [ ! -w "$output_dir" ]; then
16+
echo >&3 "$ME: ERROR: $template_dir exists, but $output_dir is not writable"
17+
return 0
18+
fi
19+
find "$template_dir" -follow -type f -name "*$suffix" -print | while read -r template; do
20+
relative_path="${template#$template_dir/}"
21+
output_path="$output_dir/${relative_path%$suffix}"
22+
subdir=$(dirname "$relative_path")
23+
# create a subdirectory where the template file exists
24+
mkdir -p "$output_dir/$subdir"
25+
echo >&3 "$ME: Running envsubst on $template to $output_path"
26+
envsubst "$defined_envs" < "$template" > "$output_path"
27+
done
28+
}
29+
30+
auto_envsubst
31+
32+
exit 0

entrypoint/docker-entrypoint.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/sh
2+
# vim:sw=4:ts=4:et
3+
4+
set -e
5+
6+
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
7+
exec 3>&1
8+
else
9+
exec 3>/dev/null
10+
fi
11+
12+
if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
13+
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
14+
echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
15+
16+
echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/"
17+
find "/docker-entrypoint.d/" -follow -type f -print | sort -n | while read -r f; do
18+
case "$f" in
19+
*.sh)
20+
if [ -x "$f" ]; then
21+
echo >&3 "$0: Launching $f";
22+
"$f"
23+
else
24+
# warn on shell scripts without exec bit
25+
echo >&3 "$0: Ignoring $f, not executable";
26+
fi
27+
;;
28+
*) echo >&3 "$0: Ignoring $f";;
29+
esac
30+
done
31+
32+
echo >&3 "$0: Configuration complete; ready for start up"
33+
else
34+
echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration"
35+
fi
36+
fi
37+
38+
exec "$@"

0 commit comments

Comments
 (0)