mirror of
https://github.com/penpot/penpot.git
synced 2026-07-31 18:36:18 +00:00
🐳 Migrate penpot images to DHI (#10734)
Move Dockerfile.frontend, .backend, .exporter, .mcp and .storybook under docker/images/ from ubuntu:26.04 / nginx-unprivileged / a manual Node tarball install to Docker Hardened Images (Debian 13, or Alpine for storybook). storybook and mcp get a true non-dev runtime; frontend, backend and exporter keep the -dev tag as their final image, since each needs a shell and/or package manager at container runtime (nginx templating, fontforge/python3, and a headless-browser stack, respectively).
This commit is contained in:
parent
e741313add
commit
97a833f1e7
15
.github/workflows/build-docker.yml
vendored
15
.github/workflows/build-docker.yml
vendored
@ -107,6 +107,19 @@ jobs:
|
||||
username: ${{ secrets.PUB_DOCKER_USERNAME }}
|
||||
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
|
||||
|
||||
# Frontend, backend, exporter, storybook and mcp now build FROM
|
||||
# Docker Hardened Images (dhi.io). DHI is free (Apache 2.0, no
|
||||
# subscription), but pulling from it still requires an
|
||||
# authenticated login -- a separate `docker login` against a
|
||||
# different registry host, even though it reuses the same
|
||||
# PUB_DOCKER_* credentials as the DockerHub login above.
|
||||
- name: Login to Docker Hardened Images registry (base image pull)
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: dhi.io
|
||||
username: ${{ secrets.PUB_DOCKER_USERNAME }}
|
||||
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
|
||||
|
||||
# Every build pushes an immutable `build-<key>` tag; if it already
|
||||
# exists in the registry, this exact image was already built and the
|
||||
# whole build can be skipped. Moving tags are handled by `promote`.
|
||||
@ -164,6 +177,8 @@ jobs:
|
||||
file: ./docker/images/Dockerfile.${{ matrix.image }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
provenance: mode=max
|
||||
sbom: true
|
||||
# Immutable tag only; branch tags are moved atomically for the
|
||||
# whole image set by the `promote` job.
|
||||
tags: ${{ secrets.DOCKER_REGISTRY }}/${{ matrix.image }}:build-${{ needs.prepare.outputs.build_key }}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:26.04 AS build
|
||||
FROM dhi.io/debian-base:trixie-debian13-dev AS build
|
||||
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||
|
||||
ENV LANG='C.UTF-8' \
|
||||
@ -47,7 +47,8 @@ RUN set -eux; \
|
||||
--add-modules java.base,jdk.net,jdk.management.agent,java.se,jdk.compiler,jdk.javadoc,jdk.attach,jdk.unsupported,jdk.jfr,jdk.jcmd \
|
||||
--output /opt/jre;
|
||||
|
||||
FROM ubuntu:26.04 AS image
|
||||
|
||||
FROM dhi.io/debian-base:trixie-debian13-dev AS image
|
||||
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||
|
||||
ENV LANG='C.UTF-8' \
|
||||
@ -55,11 +56,13 @@ ENV LANG='C.UTF-8' \
|
||||
JAVA_HOME="/opt/jre" \
|
||||
PATH=/opt/jre/bin:/opt/imagick/bin:$PATH \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
TZ=Etc/UTC
|
||||
TZ=Etc/UTC \
|
||||
LD_LIBRARY_PATH=/opt/imagick/lib/deps
|
||||
|
||||
RUN set -ex; \
|
||||
useradd -U -M -u 1001 -s /bin/false -d /opt/penpot penpot; \
|
||||
apt-get -qq update; \
|
||||
apt-get -qqy --no-install-recommends install passwd; \
|
||||
useradd -U -M -u 1001 -s /bin/false -d /opt/penpot penpot; \
|
||||
apt-get -qq dist-upgrade; \
|
||||
apt-get -qqy --no-install-recommends install \
|
||||
ca-certificates \
|
||||
@ -71,7 +74,7 @@ RUN set -ex; \
|
||||
libglib2.0-0 \
|
||||
libgomp1 \
|
||||
libheif1 \
|
||||
libjpeg-turbo8 \
|
||||
libjpeg62-turbo \
|
||||
liblcms2-2 \
|
||||
libopenexr-3-1-30 \
|
||||
libopenjp2-7 \
|
||||
@ -81,7 +84,7 @@ RUN set -ex; \
|
||||
libwebp7 \
|
||||
libwebpdemux2 \
|
||||
libwebpmux3 \
|
||||
libxml2-16 \
|
||||
libxml2 \
|
||||
libzip5 \
|
||||
libzstd1 \
|
||||
python3 \
|
||||
@ -100,7 +103,7 @@ RUN set -ex; \
|
||||
chown -R penpot:penpot /opt/data;
|
||||
|
||||
COPY --from=build /opt/jre /opt/jre
|
||||
COPY --from=penpotapp/imagemagick:7.1.2-24 /opt/imagick /opt/imagick
|
||||
COPY --from=penpotapp/imagemagick:7.1.2-27 /opt/imagick /opt/imagick
|
||||
|
||||
COPY files/imagemagick-policy.xml /opt/imagick/etc/ImageMagick-7/policy.xml
|
||||
|
||||
|
||||
@ -1,18 +1,16 @@
|
||||
FROM ubuntu:26.04
|
||||
FROM dhi.io/node:24.18.1-debian13-dev
|
||||
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
LC_ALL=en_US.UTF-8 \
|
||||
NODE_VERSION=v24.18.1 \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
PATH=/opt/node/bin:/opt/imagick/bin:$PATH \
|
||||
PATH=/opt/imagick/bin:$PATH \
|
||||
PLAYWRIGHT_BROWSERS_PATH=/opt/penpot/browsers
|
||||
|
||||
RUN set -ex; \
|
||||
useradd -U -M -u 1001 -s /bin/false -d /opt/penpot penpot; \
|
||||
mkdir -p /etc/resolvconf/resolv.conf.d; \
|
||||
echo "nameserver 127.0.0.11" > /etc/resolvconf/resolv.conf.d/tail; \
|
||||
apt-get -qq update; \
|
||||
apt-get -qqy --no-install-recommends install passwd; \
|
||||
useradd -U -M -u 1001 -s /bin/false -d /opt/penpot penpot; \
|
||||
apt-get -qq dist-upgrade; \
|
||||
apt-get -qqy --no-install-recommends install \
|
||||
curl \
|
||||
@ -44,16 +42,16 @@ RUN set -ex; \
|
||||
fonts-freefont-ttf \
|
||||
poppler-utils \
|
||||
\
|
||||
libasound2t64 \
|
||||
libatk-bridge2.0-0t64 \
|
||||
libatk1.0-0t64 \
|
||||
libatspi2.0-0t64 \
|
||||
libasound2 \
|
||||
libatk-bridge2.0-0 \
|
||||
libatk1.0-0 \
|
||||
libatspi2.0-0 \
|
||||
libcairo2 \
|
||||
libcups2t64 \
|
||||
libcups2 \
|
||||
libdbus-1-3 \
|
||||
libdrm2 \
|
||||
libgbm1 \
|
||||
libglib2.0-0t64 \
|
||||
libglib2.0-0 \
|
||||
libnspr4 \
|
||||
libnss3 \
|
||||
libpango-1.0-0 \
|
||||
@ -68,7 +66,7 @@ RUN set -ex; \
|
||||
\
|
||||
libgomp1 \
|
||||
libheif1 \
|
||||
libjpeg-turbo8 \
|
||||
libjpeg62-turbo \
|
||||
liblcms2-2 \
|
||||
libopenexr-3-1-30 \
|
||||
libopenjp2-7 \
|
||||
@ -78,44 +76,26 @@ RUN set -ex; \
|
||||
libwebp7 \
|
||||
libwebpdemux2 \
|
||||
libwebpmux3 \
|
||||
libxml2-16 \
|
||||
libxml2 \
|
||||
libzip5 \
|
||||
libzstd1 \
|
||||
; \
|
||||
apt-get clean; \
|
||||
rm -rf /var/lib/apt/lists/*;
|
||||
|
||||
RUN set -eux; \
|
||||
ARCH="$(dpkg --print-architecture)"; \
|
||||
case "${ARCH}" in \
|
||||
aarch64|arm64) \
|
||||
BINARY_URL="https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-arm64.tar.gz"; \
|
||||
;; \
|
||||
amd64|x86_64) \
|
||||
BINARY_URL="https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-x64.tar.gz"; \
|
||||
;; \
|
||||
*) \
|
||||
echo "Unsupported arch: ${ARCH}"; \
|
||||
exit 1; \
|
||||
;; \
|
||||
esac; \
|
||||
curl -LfsSo /tmp/nodejs.tar.gz ${BINARY_URL}; \
|
||||
mkdir -p /opt/node; \
|
||||
cd /opt/node; \
|
||||
tar -xf /tmp/nodejs.tar.gz --strip-components=1; \
|
||||
chown -R root /opt/node; \
|
||||
rm -rf /tmp/nodejs.tar.gz; \
|
||||
corepack enable; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
mkdir -p /opt/penpot; \
|
||||
chown -R penpot:penpot /opt/penpot;
|
||||
|
||||
ARG BUNDLE_PATH="./bundle-exporter/"
|
||||
COPY --chown=penpot:penpot $BUNDLE_PATH /opt/penpot/exporter/
|
||||
COPY --from=penpotapp/imagemagick:7.1.2-24 /opt/imagick /opt/imagick
|
||||
COPY --from=penpotapp/imagemagick:7.1.2-27 /opt/imagick /opt/imagick
|
||||
|
||||
WORKDIR /opt/penpot/exporter
|
||||
|
||||
# DHI Node image installs Node at the system level (symlinked into
|
||||
# /usr/bin), so `./setup`'s internal `corepack enable` needs root to write
|
||||
# there. Ownership is fixed right after.
|
||||
RUN ./setup && chown -R penpot:penpot /opt/penpot/exporter
|
||||
|
||||
USER penpot:penpot
|
||||
|
||||
RUN ./setup
|
||||
|
||||
CMD ["node", "app.js"]
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
FROM nginxinc/nginx-unprivileged:1.31.1-alpine
|
||||
FROM dhi.io/nginx:1.31.1-debian13-dev
|
||||
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
USER root
|
||||
|
||||
RUN set -ex; \
|
||||
apk update; \
|
||||
apk upgrade; \
|
||||
apk add --no-cache bash gettext; \
|
||||
rm -rf /var/cache/apk/*; \
|
||||
addgroup -g 1001 penpot; \
|
||||
adduser -D -H -u 1001 -s /bin/false -h /opt/penpot -G penpot penpot; \
|
||||
apt-get -qq update; \
|
||||
apt-get -qq -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade; \
|
||||
apt-get -qqy -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --no-install-recommends install bash gettext-base passwd; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
groupadd -f -g 1001 penpot; \
|
||||
useradd -M -u 1001 -s /usr/sbin/nologin -d /opt/penpot -g penpot penpot; \
|
||||
mkdir -p /opt/data/assets; \
|
||||
chown -R penpot:penpot /opt/data; \
|
||||
mkdir -p /etc/nginx/overrides/main.d/; \
|
||||
|
||||
@ -1,61 +1,26 @@
|
||||
FROM ubuntu:26.04
|
||||
FROM dhi.io/node:24.18.1-debian13-dev AS build
|
||||
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ARG BUNDLE_PATH="./bundle-mcp/"
|
||||
COPY $BUNDLE_PATH /opt/penpot/mcp/
|
||||
|
||||
WORKDIR /opt/penpot/mcp
|
||||
|
||||
RUN ./setup
|
||||
|
||||
|
||||
FROM dhi.io/node:24.18.1-debian13 AS image
|
||||
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
LC_ALL=en_US.UTF-8 \
|
||||
NODE_VERSION=v24.18.1 \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
PATH=/opt/node/bin:$PATH \
|
||||
PENPOT_MCP_SERVER_HOST=0.0.0.0
|
||||
|
||||
RUN set -ex; \
|
||||
useradd -U -M -u 1001 -s /bin/false -d /opt/penpot penpot; \
|
||||
mkdir -p /etc/resolvconf/resolv.conf.d; \
|
||||
echo "nameserver 127.0.0.11" > /etc/resolvconf/resolv.conf.d/tail; \
|
||||
apt-get -qq update; \
|
||||
apt-get -qq dist-upgrade; \
|
||||
apt-get -qqy --no-install-recommends install \
|
||||
curl \
|
||||
tzdata \
|
||||
locales \
|
||||
ca-certificates \
|
||||
; \
|
||||
apt-get clean; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \
|
||||
locale-gen; \
|
||||
find /usr/share/i18n/locales/ -type f ! -name "en_US" ! -name "POSIX" ! -name "C" -delete;
|
||||
|
||||
RUN set -eux; \
|
||||
ARCH="$(dpkg --print-architecture)"; \
|
||||
case "${ARCH}" in \
|
||||
aarch64|arm64) \
|
||||
BINARY_URL="https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-arm64.tar.gz"; \
|
||||
;; \
|
||||
amd64|x86_64) \
|
||||
BINARY_URL="https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-x64.tar.gz"; \
|
||||
;; \
|
||||
*) \
|
||||
echo "Unsupported arch: ${ARCH}"; \
|
||||
exit 1; \
|
||||
;; \
|
||||
esac; \
|
||||
curl -LfsSo /tmp/nodejs.tar.gz ${BINARY_URL}; \
|
||||
mkdir -p /opt/node; \
|
||||
cd /opt/node; \
|
||||
tar -xf /tmp/nodejs.tar.gz --strip-components=1; \
|
||||
chown -R root /opt/node; \
|
||||
rm -rf /tmp/nodejs.tar.gz; \
|
||||
corepack enable; \
|
||||
mkdir -p /opt/penpot; \
|
||||
chown -R penpot:penpot /opt/penpot;
|
||||
|
||||
ARG BUNDLE_PATH="./bundle-mcp/"
|
||||
COPY --chown=penpot:penpot $BUNDLE_PATH /opt/penpot/mcp/
|
||||
COPY --from=build --chown=node:node /opt/penpot/mcp /opt/penpot/mcp
|
||||
|
||||
WORKDIR /opt/penpot/mcp
|
||||
USER penpot:penpot
|
||||
|
||||
RUN ./setup
|
||||
USER node
|
||||
|
||||
CMD ["node", "index.js", "--multi-user"]
|
||||
|
||||
@ -1,24 +1,11 @@
|
||||
FROM nginxinc/nginx-unprivileged:1.31.1-alpine
|
||||
FROM dhi.io/nginx:1.31.1-alpine3.22
|
||||
LABEL maintainer="Penpot <docker@penpot.app>"
|
||||
|
||||
USER root
|
||||
|
||||
RUN set -ex; \
|
||||
apk update; \
|
||||
apk upgrade; \
|
||||
rm -rf /var/cache/apk/*; \
|
||||
addgroup -g 1001 penpot; \
|
||||
adduser -D -H -u 1001 -s /bin/false -h /opt/penpot -G penpot penpot;
|
||||
|
||||
ARG BUNDLE_PATH="./bundle-storybook/"
|
||||
COPY $BUNDLE_PATH /var/www/
|
||||
COPY ./files/nginx.storybook.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
RUN chown -R 1001:0 /var/cache/nginx; \
|
||||
chmod -R g+w /var/cache/nginx; \
|
||||
chown -R 1001:0 /etc/nginx; \
|
||||
chmod -R g+w /etc/nginx; \
|
||||
chown -R 1001:0 /var/www; \
|
||||
chmod -R g+w /var/www;
|
||||
COPY --chown=65532:65532 $BUNDLE_PATH /var/www/
|
||||
COPY --chown=65532:65532 ./files/nginx.storybook.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
USER penpot:penpot
|
||||
# Already the default user in the DHI runtime; explicit for clarity. Numeric
|
||||
# UID, not by name -- this image has no "nonroot" entry in /etc/passwd.
|
||||
USER 65532:65532
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user