docker daemon
Enable buildkit
Add to /etc/docker/daemon.json
:
{
"features": {
"buildkit": true
},
"builder": {
"gc": {
"enabled": true
}
}
}
docker-compose
Devices
services:
web:
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
Labels
services:
web:
labels:
com.example.description: "Accounting web app"
External Network
# join a pre-existing network
networks:
default:
external:
name: frontend
Dockerfile
Docker Stop Signal
# https://www.haproxy.org/download/1.8/doc/management.txt
# "4. Stopping and restarting HAProxy"
# "when the SIGTERM signal is sent to the haproxy process, it immediately quits and all established connections are closed"
# "graceful stop is triggered when the SIGUSR1 signal is sent to the haproxy process"
STOPSIGNAL SIGUSR1
imagemagick
# https://github.com/docker-library/redmine/issues/132
# (without "gsfonts" we get "Magick::ImageMagickError (non-conforming drawing primitive definition `text' @ error/draw.c/DrawImage/3265):")
gsfonts \
imagemagick \
vim
# vim:set ft=dockerfile:
FROM alpine:latest
path update
ENV JAVA_HOME /opt/openjdk-12
ENV PATH $JAVA_HOME/bin:$PATH
download & extract tar.gz
&& wget -O haproxy.tar.gz "$HAPROXY_URL" \
&& echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c \
&& mkdir -p /usr/src/haproxy \
&& tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1 \
&& rm haproxy.tar.gz
# vs.
RUN set -eux; \
\
wget -O /openjdk.tgz "$JAVA_URL"; \
echo "$JAVA_SHA256 */openjdk.tgz" | sha256sum -c -; \
mkdir -p "$JAVA_HOME"; \
tar --extract --file /openjdk.tgz --directory "$JAVA_HOME" --strip-components 1; \
rm /openjdk.tgz; \
# vs.
RUN set -eux; \
\
curl -fL -o /openjdk.tgz "$JAVA_URL"; \
echo "$JAVA_SHA256 */openjdk.tgz" | sha256sum -c -; \
mkdir -p "$JAVA_HOME"; \
tar --extract --file /openjdk.tgz --directory "$JAVA_HOME" --strip-components 1; \
rm /openjdk.tgz;
# vs.
RUN set -ex; \
curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \
echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \
# upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
tar -xzf wordpress.tar.gz -C /usr/src/; \
rm wordpress.tar.gz; \
chown -R www-data:www-data /usr/src/wordpress
# vs.
RUN set -ex; \
curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \
echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \
# upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
tar -xzf wordpress.tar.gz -C /usr/src/; \
rm wordpress.tar.gz; \
chown -R www-data:www-data /usr/src/wordpress
# vs.
tar -xJf ruby.tar.xz -C /usr/src/ruby --strip-components=1 \
# vs.
ENV REDMINE_DOWNLOAD_MD5 816992eb005cbaa636ad7f8962cb6e0d
RUN wget -O redmine.tar.gz "https://www.redmine.org/releases/redmine-${REDMINE_VERSION}.tar.gz" \
&& echo "$REDMINE_DOWNLOAD_MD5 redmine.tar.gz" | md5sum -c - \
gpg dirmgr explained
# https://bugs.debian.org/830696 (apt uses gpgv by default in newer releases, rather than gpg)
RUN set -ex; \
apt-get update; \
if ! which gpg; then \
apt-get install -y --no-install-recommends gnupg; \
fi; \
# Ubuntu includes "gnupg" (not "gnupg2", but still 2.x), but not dirmngr, and gnupg 2.x requires dirmngr
# so, if we're not running gnupg 1.x, explicitly install dirmngr too
if ! gpg --version | grep -q '^gpg (GnuPG) 1\.'; then \
apt-get install -y --no-install-recommends dirmngr; \
fi; \
rm -rf /var/lib/apt/lists/*
purge
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*
list what exposed ports do
cassandra
# 7000: intra-node communication
# 7001: TLS intra-node communication
# 7199: JMX
# 9042: CQL
# 9160: thrift service
EXPOSE 7000 7001 7199 9042 9160
gosu
debian
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r rabbitmq && useradd -r -d /var/lib/rabbitmq -m -g rabbitmq rabbitmq
# vs.
RUN groupadd user && useradd --create-home --home-dir /home/user -g user user
# vs.
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mongodb && useradd -r -g mongodb mongodb
RUN mkdir -p /data/db /data/configdb \
&& chown -R mongodb:mongodb /data/db /data/configdb
VOLUME /data/db /data/configdb
# vs.
#alpine
# ensure logstash user exists
RUN addgroup -S logstash && adduser -S -G logstash logstash
#ruby + debian cleanup
apt-get purge -y --auto-remove a b c \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /tmp/* /var/tmp/* /usr/lib/ruby/gems/*/cache/*.gem
# debian
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
# redhat
RUN yum update -y && yum install -y fontconfig freetype && yum clean all
copy with proper permissions
COPY --chown=1000:0 src dst
# Ensure gid 0 write permissions for Openshift.
RUN find /usr/share/kibana -gid 0 -and -not -perm /g+w -exec chmod g+w {} \;
su-exec
# grab su-exec for easy step-down from root
RUN apk add --no-cache 'su-exec>=0.2'
setgid
chown -R 1000:0 . && \
chmod -R g=u /usr/share/kibana && \
find /usr/share/kibana -type d -exec chmod g+s {} \;
npm
npm install --production; \
npm cache clean; \
rm -rf /tmp/npm*
gosu
# grab gosu for easy step-down from root
RUN set -x \
&& export GOSU_VERSION=1.10 \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \
&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \
&& export GNUPGHOME="$(mktemp -d)" \
&& gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
&& gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
&& rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true \
&& apt-get purge -y --auto-remove wget
# vs.
# grab gosu for easy step-down from root
ENV GOSU_VERSION 1.10
RUN set -x \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \
&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \
&& export GNUPGHOME="$(mktemp -d)" \
&& gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
&& gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
&& { command -v gpgconf && gpgconf --kill all || :; } \
&& rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true
tini
# grab tini for signal processing and zombie killing
RUN set -x \
&& export TINI_VERSION=0.14.0 \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/v$TINI_VERSION/tini" \
&& wget -O /usr/local/bin/tini.asc "https://github.com/krallin/tini/releases/download/v$TINI_VERSION/tini.asc" \
&& export GNUPGHOME="$(mktemp -d)" \
&& gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys 6380DC428747F6C393FEACA59A84159D7001A4E5 \
&& gpg --batch --verify /usr/local/bin/tini.asc /usr/local/bin/tini \
&& rm -r "$GNUPGHOME" /usr/local/bin/tini.asc \
&& chmod +x /usr/local/bin/tini \
&& tini -h \
&& apt-get purge -y --auto-remove wget
node
RUN set -x \
&& export NODE_VERSION=4.7.0 \
&& export GNUPGHOME="$(mktemp -d)" \
# gpg keys listed at https://github.com/nodejs/node
&& for key in \
9554F04D7259F04124DE6B476D5A82AC7E37093B \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
; do \
gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
done \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& wget "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" \
&& wget "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --verify SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt.asc | sha256sum -c - \
&& tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 \
&& rm -r "$GNUPGHOME" "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc \
&& apt-get purge -y --auto-remove wget
redis
RUN set -x \
&& export REDIS_VERSION=3.2.6 \
&& export REDIS_DOWNLOAD_SHA1=0c7bc5c751bdbc6fabed178db9cdbdd948915d1b \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /usr/src/redis \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-$REDIS_VERSION.tar.gz" \
&& echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& rm redis.tar.gz \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove wget
docker
RUN set -x \
&& export DOCKER_VERSION=18.03.1 \
&& export DOCKER_SHA256=0e245c42de8a21799ab11179a4fce43b494ce173a8a2d6567ea6825d6c5265aa \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& wget -O docker.tgz "https://download.docker.com/linux/static/stable/x86_64/docker-$DOCKER_VERSION-ce.tgz" \
&& echo "${DOCKER_SHA256} *docker.tgz" | sha256sum -c - \
&& tar -zxvf docker.tgz \
&& mv docker/* /usr/local/bin/ \
&& rmdir docker \
&& rm docker.tgz \
&& docker -v \
&& apt-get purge -y --auto-remove wget
google cloud sdk
RUN set -x \
&& export GCLOUD_SHA256=71229c3cd2290a60310c5ac9fb2e660cb1a4a0f637704b4b3af0a1f75f649e5f \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& wget -O gcloud.tgz "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-201.0.0-linux-x86_64.tar.gz" \
&& echo "${GCLOUD_SHA256} *gcloud.tgz" | sha256sum -c - \
&& tar -zxvf gcloud.tgz -C /opt \
&& rm gcloud.tgz \
&& apt-get purge -y --auto-remove wget
ENV PATH="${PATH}:/opt/google-cloud-sdk/bin"
kubectl
RUN set -x \
&& export KUBECTL_VERSION=v1.11.0 \
&& export KUBECTL_SHA256=7fc84102a20aba4c766245714ce9555e3bf5d4116aab38a15b11419070a0fa90 \
&& apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/* \
&& wget -O kubectl "https://storage.googleapis.com/kubernetes-release/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl" \
&& echo "${KUBECTL_SHA256} *kubectl" | sha256sum -c - \
&& install -m 755 kubectl /usr/local/bin/ \
&& kubectl --help \
&& apt-get purge -y --auto-remove wget
pip
# Sane defaults for pip
ENV PIP_NO_CACHE_DIR off
ENV PIP_DISABLE_PIP_VERSION_CHECK on
ENV PYTHONUNBUFFERED 1
locale
# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default
RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.utf8
tomcat
https://github.com/Unidata/tomcat-docker/blob/master/Dockerfile
FROM tomcat:8.5-jre8
RUN
# Eliminate default web applications
###
rm -rf ${CATALINA_HOME}/webapps/* && \
rm -rf ${CATALINA_HOME}/server/webapps/* && \
# Obscuring server info
###
cd ${CATALINA_HOME}/lib && \
mkdir -p org/apache/catalina/util/ && \
unzip -j catalina.jar org/apache/catalina/util/ServerInfo.properties \
-d org/apache/catalina/util/ && \
sed -i 's/server.info=.*/server.info=Apache Tomcat/g' \
org/apache/catalina/util/ServerInfo.properties && \
zip -ur catalina.jar \
org/apache/catalina/util/ServerInfo.properties && \
rm -rf org && cd ${CATALINA_HOME} \
sed -i 's/<Connector/<Connector server="Apache" secure="true"/g' \
${CATALINA_HOME}/conf/server.xml && \
sed -i 's/resourceName="UserDatabase"\/>/resourceName="UserDatabase"><CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="SHA" \/><\/Realm>/g' \
${CATALINA_HOME}/conf/server.xml && \
###
# Setting restrictive umask container-wide
###
echo "session optional pam_umask.so" >> /etc/pam.d/common-session && \
sed -i 's/UMASK.*022/UMASK 007/g' /etc/login.defs
gosu tomcat
#!/bin/bash
set -e
# preferable to fire up Tomcat via start-tomcat.sh which will start Tomcat with
# security manager, but inheriting containers can also start Tomcat via
# catalina.sh
if [ "$1" = 'start-tomcat.sh' ] || [ "$1" = 'catalina.sh' ]; then
USER_ID=${TOMCAT_USER_ID:-1000}
GROUP_ID=${TOMCAT_GROUP_ID:-1000}
###
# Tomcat user
###
groupadd -r tomcat -g ${GROUP_ID} && \
useradd -u ${USER_ID} -g tomcat -d ${CATALINA_HOME} -s /sbin/nologin \
-c "Tomcat user" tomcat
###
# Change CATALINA_HOME ownership to tomcat user and tomcat group
# Restrict permissions on conf
###
chown -R tomcat:tomcat ${CATALINA_HOME} && chmod 400 ${CATALINA_HOME}/conf/*
sync
exec gosu tomcat "$@"
fi
exec "$@"
#!/bin/sh
#source vars if file exists
DEFAULT=/etc/default/fluentd
if [ -r $DEFAULT ]; then
set -o allexport
source $DEFAULT
set +o allexport
fi
# If the user has supplied only arguments append them to `fluentd` command
if [ "${1#-}" != "$1" ]; then
set -- fluentd "$@"
fi
# If user does not supply config file or plugins, use the default
if [ "$1" = "fluentd" ]; then
if ! echo $@ | grep ' \-c' ; then
set -- "$@" -c /fluentd/etc/fluent.conf
fi
if ! echo $@ | grep ' \-p' ; then
set -- "$@" -p /fluentd/plugins
fi
fi
exec gosu fluent "$@"
Secure repository setup
RUN set -x \
&& apt-get update && apt-get install -y --no-install-recommends apt-transport-https && rm -rf /var/lib/apt/lists/* \
&& echo 'deb https://artifacts.elastic.co/packages/5.x/apt stable main' > /etc/apt/sources.list.d/elasticsearch.list
# vs.
RUN echo "deb http://$MONGO_REPO/apt/debian jessie/${MONGO_PACKAGE%-unstable}/$MONGO_MAJOR main" | tee "/etc/apt/sources.list.d/${MONGO_PACKAGE%-unstable}.list"
create application folder structure
RUN set -ex \
&& for path in \
./data \
./logs \
./config \
./config/scripts \
/usr/share/elasticsearch \
; do \
mkdir -p "$path"; \
chown -R elasticsearch:elasticsearch "$path"; \
done
Download and clean up in one layer
ENV RUNC_VERSION v1.0.0-rc5
RUN set -eux; \
wget -O runc.tgz "https://github.com/opencontainers/runc/archive/${RUNC_VERSION}.tar.gz"; \
mkdir -p /go/src/github.com/opencontainers/runc; \
tar -xf runc.tgz -C /go/src/github.com/opencontainers/runc --strip-components=1; \
rm runc.tgz
Package Manager tricks
RUN apk add --no-cache Package1 [PackageN]
Metadata
Make sure to add ARG
statements as late as possible to not invalidate the layer cache needlessly.
Each ARG
will be prepended to all subsequent RUN
statements, i.e. building an image with the following Dockerfile docker --pull --tag foo:latest --build-arg GIT_COMMIT=46e24af6 --build-arg USERNAME=flask .
FROM alpine:latest
ARG GIT_COMMIT=unknown
ARG USERNAME=user
RUN mkdir -p /home/${USERNAME}/app
RUN make
Effectively results in the following calls:
GIT_COMMIT=46e24af6 USERNAME=flask mkdir -p /home/flask/app
GIT_COMMIT=46e24af6 USERNAME=flask make
Since the git commit hash will typically change with each build the build will not make good use of Docker’s layer cache
ARG GIT_COMMIT=unknown
ARG GIT_BRANCH=unknown
ARG GIT_TAG=unknown
ARG BUILD_TIME=unknown
# metadata
# https://github.com/opencontainers/image-spec/blob/master/annotations.md
LABEL maintainer="DevOps Team <devops@company.com>" \
org.opencontainers.image.title="Company Inc. File Downloader" \
org.opencontainers.image.description="Offers Basic Auth protected downloads of container files." \
org.opencontainers.image.vendor="Company Inc." \
org.opencontainers.image.created="$BUILD_TIME" \
org.opencontainers.image.revision="$GIT_COMMIT" \
org.opencontainers.image.version="$GIT_TAG"
Python
FROM python:3.6-alpine3.8
# Add non-changing settings at the top to profit from docker layer caching
ENV FLASK_APP=logapp.py \
PYTHONUNBUFFERED=TRUE
RUN addgroup -g 1000 -S flask && \
adduser -u 1000 -S flask -G flask
WORKDIR /home/flask/app/web
# Skips pip install if requirements hasn't changed
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# Copy app files
COPY *.py /home/flask/app/web
# Make the app run under non-root user & fix permissions
# WORKDIR sets root:root :(
RUN chown -R flask:flask /home/flask
USER flask
CMD ["gunicorn", "-b", ":8000", "-w", "1", "--access-logfile", "-", "--error-logfile", "-", "flask_frontend:app"]
Golang
#### Build container ####
FROM golang:1.10-alpine3.8 AS build-env
# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git make
RUN go get github.com/golang/dep/cmd/dep
# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/gitlab.company.com/dev_team/middleware/
WORKDIR /go/src/gitlab.company.com/dev_team/middleware/
ARG GITLAB_USER
ARG GITLAB_PWD
# Set up git config
RUN git config --global url."https://$GITLAB_USER:$GITLAB_PWD@gitlab.company.com".insteadof https://gitlab.company.com
# Install library dependencies
#
# creates the vendor folder from a valid Gopkg.toml and Gopkg.lock
# without checking for Go code. This is especially useful for builds
# inside docker utilizing cache layers.
RUN dep ensure -vendor-only
# Copy the entire project ...
# This layer is rebuilt when a file changes in the project directory
COPY . .
ARG GIT_COMMIT=unknown
ARG GIT_BRANCH=unknown
ARG GIT_TAG=unknown
ARG BUILD_TIME=unknown
# ... and build a static binary but disable Go's C-libary integration
# https://dave.cheney.net/tag/cgo
#RUN CGO_ENABLED=0 go build -o /go/bin/middleware cmd/middleware/main.go
RUN make release-docker OUTPUT=/go/bin/middleware
#### Runtime container ####
FROM alpine:3.8 AS img-prod
# Add CA certificates to communicate with BBD over https
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*
ENV DOCKERIZE_VERSION v0.6.1
WORKDIR /app
RUN wget -q https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
ARG GIT_COMMIT=unknown
ARG GIT_BRANCH=unknown
ARG GIT_TAG=unknown
ARG BUILD_TIME=unknown
# metadata
# https://github.com/opencontainers/image-spec/blob/master/annotations.md
LABEL maintainer="DevOps Team <devops@company.com>" \
org.opencontainers.image.title="Flux Capacitor Service (middleware)" \
org.opencontainers.image.description="Project customer and dealer middleware" \
org.opencontainers.image.vendor="Company Inc." \
org.opencontainers.image.created="$BUILD_TIME" \
org.opencontainers.image.revision="$GIT_COMMIT" \
org.opencontainers.image.version="$GIT_TAG"
LABEL GIT_COMMIT="$GIT_COMMIT" \
GIT_BRANCH="$GIT_BRANCH" \
GIT_TAG="$GIT_TAG" \
BUILD_TIME="$BUILD_TIME"
# Copy app and config into final image
COPY --from=build-env /go/bin/middleware /app/middleware
COPY cfg/config.template /app/config.template
EXPOSE 4567
ENTRYPOINT ["dockerize","-template","/app/config.template:/app/config_middleware.toml"]
CMD ["/app/middleware","--config=/app/config_middleware.toml"]