Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: Docker

# Many ports copyied from https://docs.docker.com/build/ci/github-actions/manage-tags-labels/

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
Expand All @@ -18,23 +20,31 @@ env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
IMAGE_NAME: pflum/docker-postfix


jobs:
build:

runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
include:
- variant: latest
build_arg: "INCLUDE_DEV_TOOLS=false"
tag_suffix: "latest"

- variant: latest-dev
build_arg: "INCLUDE_DEV_TOOLS=true"
tag_suffix: "latest-dev"


steps:
- name: Checkout repository
uses: actions/checkout@v3

# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
Expand All @@ -43,25 +53,16 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Setup Docker buildx
uses: docker/setup-buildx-action@v4

# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
- name: Build and push Docker image - ${{ matrix.variant }}
id: build-and-push
uses: docker/build-push-action@v7
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

build-args: ${{ matrix.build_arg }}
tags: |
${{ github.ref == 'refs/heads/master' && format('{0}/{1}:{2}', env.REGISTRY, env.IMAGE_NAME, matrix.tag_suffix) || format('{0}/{1}:{2}-{3}', env.REGISTRY, env.IMAGE_NAME, github.ref_name, matrix.tag_suffix) }}
${{ github.ref == 'refs/heads/master' && format('{0}/{1}:{2}-{3}', env.REGISTRY, env.IMAGE_NAME, matrix.tag_suffix, github.sha) || format('{0}/{1}:{2}-{3}-{4}', env.REGISTRY, env.IMAGE_NAME, github.ref_name, matrix.tag_suffix, github.sha) }}
10 changes: 8 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
ARG INCLUDE_DEV_TOOLS=false

FROM alpine:3.22

RUN apk add --no-cache --update \
bash \
ca-certificates \
postfix \
postfix-doc \
postfix-ldap \
tzdata

RUN if [ "$INCLUDE_DEV_TOOLS" = "true" ]; then \
apk add --no-cache bash bash-doc; \
fi

EXPOSE 25 465 587

VOLUME [ "/var/spool/postfix" ]

COPY VERSION /
COPY entrypoint.sh /

ENTRYPOINT ["/usr/sbin/postfix", "start-fg"]
ENTRYPOINT ["/entrypoint.sh"]

87 changes: 87 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/bin/sh

logger () {
if [ "$(echo "$ENTRYPOINT_DEBUG" | tr '[:upper:]' '[:lower:]')" = "true" ]; then
echo "$1"
else
if [ -n "$2" ]; then
echo "$2"
fi
fi
}

postfix_copy_replace_env () {
# copy file and replace env vars (syntax: https://doc.dovecot.org/main/core/settings/syntax.html#environment-variables)
rm -f "$2"
LINENR=1
while IFS= read -r line; do
# shellcheck disable=SC2016
MATCHES="$(echo "$line" | grep -oE '(=|\s)(%\{env:\w+\}|\$ENV:\w+)(\s|$)')"
if [ -n "$MATCHES" ]; then
while IFS= read -r MATCH; do
ENVNAME="$(echo "$MATCH" | cut -d':' -f2 | cut -d'}' -f1)"
# shellcheck disable=SC2086
ENVVALUE="$(eval echo \"\$$ENVNAME\")"
FIRSTCHAR="$(echo "$MATCH" | cut -c1)"
LASTCHAR="$(echo "$MATCH" | rev | cut -c1)"
if [ ! "$LASTCHAR" = " " ]; then
LASTCHAR=""
fi
line="$(echo "$line" | sed "s#${MATCH}#${FIRSTCHAR}${ENVVALUE}${LASTCHAR}#")"
logger "Found $ENVNAME in ${1}:$LINENR and replaced with \"$ENVVALUE\""
done <<EOF
$MATCHES
EOF
fi
echo "$line" >> "$2"
LINENR=$((LINENR+1))
done < "$1"
}

postfix_compile_maps () {
MAPS=$(grep -vE "^\s*#.*$" "$1" | grep -oE "lmdb:/\S+")
if [ -n "$MAPS" ]; then
echo "$MAPS" | while IFS= read -r MAP; do
FILE="$(echo "$MAP" | rev | cut -d':' -f1 | rev)"
if [ -e "$FILE" ]; then
logger "Compile postfix-map $MAP"
postmap "$MAP" || logger "postmap for $MAP failed with exitcode $?" "postmap for $MAP failed"
else
logger "postmap $MAP, file not found!"
fi
done
fi
}

if [ -d "/etc/postfix.template/" ]; then
echo "Copy config from /etc/postfix.template/ to /etc/postfix/"
find "/etc/postfix.template/" ! -path "*/..*" ! -type d | while read -r file; do
targetfile="$(echo "$file" | sed 's#^/etc/postfix.template/#/etc/postfix/#')"
rm -f "$targetfile"
install -D -m 0640 "$file" "$targetfile"
done
find "/etc/postfix.template/" ! -path "*/..*" -iname "*.cf" ! -type d | while read -r sourcefile; do
targetfile="$(echo "$sourcefile" | sed 's#^/etc/postfix.template/#/etc/postfix/#')"
if [ ! "$(echo "$DISABLE_ENV_REPLACE" | tr '[:upper:]' '[:lower:]')" = true ]; then
postfix_copy_replace_env "$sourcefile" "$targetfile"
fi
if [ ! "$(echo "$DISABLE_AUTO_COMPILE_MAPS" | tr '[:upper:]' '[:lower:]')" = true ]; then
postfix_compile_maps "$targetfile"
fi
done
fi

if [ ! "$(echo "$DISABLE_POSTCONF_OVERWRITE" | tr '[:upper:]' '[:lower:]')" = true ]; then
postconf -e maillog_file=/dev/stdout
fi

if [ -d "/entrypoint.d/" ]; then
for script in /entrypoint.d/*.sh; do
if [ -x "$script" ]; then
echo "Run script $script"
"$script"
fi
done
fi

exec /usr/sbin/postfix start-fg
Loading