Skip to content

Commit 3764160

Browse files
committed
Improve docker image
1 parent 2358d82 commit 3764160

5 files changed

Lines changed: 371 additions & 36 deletions

File tree

.github/workflows/build-docker.yml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: Build docker image
2+
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.ref }}
5+
cancel-in-progress: true
6+
7+
on:
8+
push:
9+
branches:
10+
- v8
11+
tags:
12+
- '*'
13+
14+
permissions:
15+
contents: read
16+
17+
jobs:
18+
pre_job:
19+
permissions:
20+
actions: write
21+
runs-on: ubuntu-latest
22+
23+
build-docker:
24+
permissions:
25+
packages: write
26+
needs: pre_job
27+
strategy:
28+
matrix:
29+
image:
30+
- ubuntu-latest
31+
- ubuntu-24.04-arm
32+
arch:
33+
- amd64
34+
- arm64
35+
include:
36+
- image: ubuntu-latest
37+
arch: amd64
38+
- image: ubuntu-24.04-arm
39+
arch: arm64
40+
runs-on: ${{ matrix.image }}
41+
steps:
42+
- uses: actions/checkout@v4
43+
with:
44+
fetch-depth: 0 # required for composer to automatically detect root package version
45+
46+
# https://github.com/docker/setup-buildx-action
47+
- name: Set up Docker Buildx
48+
id: buildx
49+
uses: docker/setup-buildx-action@v3
50+
51+
- name: Upload docker image
52+
env:
53+
EVENT_NAME: ${{ github.event_name }}
54+
REF: ${{ github.ref }}
55+
ACTOR: ${{ github.repository_owner }}
56+
PLATFORM: ${{ matrix.image }}
57+
run: |
58+
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ghcr.io -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
59+
docker buildx build --platform linux/${{ matrix.arch }} . -f tests/dockerfiles/Dockerfile -t danog/madelineproto:next-debian-${{ matrix.arch }} --cache-from danog/madelineproto:next-debian-${{ matrix.arch }} --cache-to type=inline --push
60+
61+
merge-docker:
62+
permissions:
63+
packages: write
64+
needs: build-docker
65+
runs-on: ubuntu-latest
66+
steps:
67+
- name: Set up Docker Buildx
68+
id: buildx
69+
uses: docker/setup-buildx-action@v3
70+
71+
- uses: actions/checkout@v4
72+
73+
- name: Upload final docker image
74+
env:
75+
EVENT_NAME: ${{ github.event_name }}
76+
REF: ${{ github.ref }}
77+
ACTOR: ${{ github.repository_owner }}
78+
run: |
79+
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ghcr.io -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
80+
docker buildx imagetools create -t danog/madelineproto:debian danog/madelineproto:next-debian-{arm,amd}64
81+
#docker buildx imagetools create -t danog/madelineproto:latest danog/madelineproto:next-debian-{arm,amd}64

tests/dockerfiles/Dockerfile

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# Not alpine, due to possible performance issues of MUSL malloc.
2+
#
3+
# In theory this should not be relevant because PHP uses its own allocator,
4+
# but some one-time initialization logic inside PHP bypasses it,
5+
# which means system malloc *is* used more often especially in cases like these.
6+
#
7+
# Copied from autogenerated dockerfile in https://github.com/docker-library/php/tree/master/8.4/bookworm/cli.
8+
# Need to compile PHP from scratch in order to apply deepbind.patch and use jemalloc.
9+
10+
FROM debian:bookworm-slim
11+
12+
# prevent Debian's PHP packages from being installed
13+
# https://github.com/docker-library/php/pull/542
14+
RUN set -eux; \
15+
{ \
16+
echo 'Package: php*'; \
17+
echo 'Pin: release *'; \
18+
echo 'Pin-Priority: -1'; \
19+
} > /etc/apt/preferences.d/no-debian-php
20+
21+
# dependencies required for running "phpize"
22+
# (see persistent deps below)
23+
ENV PHPIZE_DEPS \
24+
autoconf \
25+
dpkg-dev \
26+
file \
27+
g++ \
28+
gcc \
29+
libc-dev \
30+
make \
31+
pkg-config \
32+
re2c
33+
34+
# persistent / runtime deps
35+
RUN set -eux; \
36+
apt-get update; \
37+
apt-get install -y --no-install-recommends \
38+
$PHPIZE_DEPS \
39+
ca-certificates git \
40+
curl \
41+
xz-utils \
42+
; \
43+
rm -rf /var/lib/apt/lists/*
44+
45+
RUN curl -sSLf https://github.com/danog/PrimeModule-ext/archive/refs/tags/2.0.tar.gz | tar -xz && \
46+
cd PrimeModule-ext-2.0 && \
47+
make -j$(nproc) && \
48+
make install && \
49+
cd .. && \
50+
rm -r PrimeModule-ext-2.0
51+
52+
ENV PHP_INI_DIR /usr/local/etc/php
53+
RUN set -eux; \
54+
mkdir -p "$PHP_INI_DIR/conf.d"; \
55+
# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
56+
[ ! -d /var/www/html ]; \
57+
mkdir -p /var/www/html; \
58+
chown www-data:www-data /var/www/html; \
59+
chmod 1777 /var/www/html
60+
61+
# Apply stack smash protection to functions using local buffers and alloca()
62+
# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
63+
# Enable optimization (-O2)
64+
# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
65+
# https://github.com/docker-library/php/issues/272
66+
# -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php)
67+
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -g"
68+
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
69+
ENV PHP_LDFLAGS="-Wl,-O1 -pie"
70+
71+
ENV GPG_KEYS AFD8691FDAEDF03BDF6E460563F15A9B715376CA 9D7F99A0CB8F05C8A6958D6256A97AF7600A39A6 0616E93D95AF471243E26761770426E17EBBB3DD
72+
73+
ADD tests/dockerfiles/deepbind.patch /
74+
75+
ADD https://github.com/php/php-src/commits/master.atom /dev/null
76+
77+
RUN set -eux; \
78+
\
79+
mkdir -p /usr/src; \
80+
cd /usr/src; \
81+
\
82+
git clone https://github.com/php/php-src.git --depth 1 --recursive -b PHP-8.4 php
83+
84+
RUN set -eux; \
85+
\
86+
savedAptMark="$(apt-mark showmanual)"; \
87+
apt-get update; \
88+
apt-get install -y --no-install-recommends \
89+
libargon2-dev \
90+
libcurl4-openssl-dev \
91+
libonig-dev \
92+
libreadline-dev \
93+
libsodium-dev \
94+
libsqlite3-dev pkg-config build-essential autoconf bison re2c \
95+
libssl-dev \
96+
libxml2-dev \
97+
zlib1g-dev \
98+
libcapstone-dev libffi-dev libpng-dev libgmp-dev libzip-dev \
99+
; \
100+
\
101+
export \
102+
CFLAGS="$PHP_CFLAGS" \
103+
CPPFLAGS="$PHP_CPPFLAGS" \
104+
LDFLAGS="$PHP_LDFLAGS" \
105+
# https://github.com/php/php-src/blob/d6299206dd828382753453befd1b915491b741c6/configure.ac#L1496-L1511
106+
PHP_BUILD_PROVIDER='https://github.com/docker-library/php' \
107+
PHP_UNAME='Linux - Docker' \
108+
; \
109+
cd /usr/src/php; \
110+
git rev-parse HEAD > /php-src.commit; \
111+
patch -p1 < /deepbind.patch; \
112+
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
113+
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
114+
# https://bugs.php.net/bug.php?id=74125
115+
if [ ! -d /usr/include/curl ]; then \
116+
ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
117+
fi; \
118+
./buildconf; \
119+
./configure \
120+
--build="$gnuArch" \
121+
--with-config-file-path="$PHP_INI_DIR" \
122+
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
123+
\
124+
# make sure invalid --configure-flags are fatal errors instead of just warnings
125+
--enable-option-checking=fatal \
126+
\
127+
# https://github.com/docker-library/php/issues/439
128+
--with-mhash \
129+
\
130+
# https://github.com/docker-library/php/issues/822
131+
--with-pic \
132+
\
133+
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
134+
--enable-mbstring \
135+
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
136+
--enable-mysqlnd \
137+
# https://wiki.php.net/rfc/argon2_password_hash
138+
--with-password-argon2 \
139+
# https://wiki.php.net/rfc/libsodium
140+
--with-sodium \
141+
# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
142+
--with-pdo-sqlite=/usr \
143+
--with-sqlite3=/usr \
144+
\
145+
--with-curl \
146+
--with-iconv \
147+
--with-openssl \
148+
--with-readline \
149+
--with-zlib --with-ffi --enable-intl --with-gmp --with-pdo-mysql --with-zip --enable-gd \
150+
\
151+
# in PHP 7.4+, the pecl/pear installers are officially deprecated (requiring an explicit "--with-pear")
152+
--with-pear \
153+
\
154+
--disable-cgi \
155+
--disable-phpdbg \
156+
--enable-pcntl \
157+
--enable-mbstring \
158+
--with-capstone \
159+
--with-libdir="lib/$debMultiarch" \
160+
\
161+
; \
162+
make -j "$(nproc)"; \
163+
find -type f -name '*.a' -delete; \
164+
make install; \
165+
make clean; \
166+
\
167+
# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
168+
cp -v php.ini-* "$PHP_INI_DIR/"; \
169+
\
170+
cd /; \
171+
rm -r /usr/src/php; rm deepbind.patch; \
172+
\
173+
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
174+
apt-mark auto '.*' > /dev/null; \
175+
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
176+
find /usr/local -type f -executable -exec ldd '{}' ';' \
177+
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); printf "*%s\n", so }' \
178+
| sort -u \
179+
| xargs -r dpkg-query --search \
180+
| cut -d: -f1 \
181+
| sort -u \
182+
| xargs -r apt-mark manual \
183+
; \
184+
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
185+
rm -rf /var/lib/apt/lists/*; \
186+
\
187+
# update pecl channel definitions https://github.com/docker-library/php/issues/443
188+
pecl update-channels; \
189+
rm -rf /tmp/pear ~/.pearrc; \
190+
\
191+
# smoke test
192+
php --version
193+
194+
COPY tests/dockerfiles/docker-php-* /usr/local/bin/
195+
ADD https://raw.githubusercontent.com/php/php-src/refs/heads/PHP-8.4/.gdbinit /root/.gdbinit
196+
197+
RUN pecl install igbinary uv-beta pgsql memprof
198+
199+
RUN apt-get update && apt-get -y --no-install-recommends install ssh git unzip libjemalloc2 ffmpeg nghttp2 && apt-get clean && rm -rf /var/lib/apt/lists/*
200+
201+
ADD tests/dockerfiles/php.ini /usr/local/etc/php/php.ini
202+
203+
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
204+
205+
RUN ln -s "$(dpkg -L libjemalloc2 | grep libjemalloc.so | head -1)" /usr/lib/libjemalloc.so
206+
207+
FROM scratch
208+
209+
COPY --from=0 / /
210+
211+
LABEL "repository"="http://github.com/danog/MadelineProto"
212+
LABEL "homepage"="http://docs.madelineproto.xyz"
213+
LABEL "maintainer"="Daniil Gentili <daniil@daniil.it>"
214+
215+
LABEL "org.opencontainers.image.source"="http://github.com/danog/MadelineProto"
216+
LABEL "org.opencontainers.image.description"=" Async PHP client API for the telegram MTProto protocol"
217+
LABEL "org.opencontainers.image.licenses"=AGPL-3.0-only
218+
219+
ENV PHP_INI_DIR /usr/local/etc/php
220+
ENV PATH=/composer/vendor/bin:${PATH}
221+
222+
ENV USE_ZEND_ALLOC=0
223+
ENV LD_PRELOAD=/usr/lib/libjemalloc.so
224+
225+
RUN php -v
226+
227+
STOPSIGNAL SIGTERM
228+
229+
WORKDIR /app
230+
231+
CMD ["php", "/app/bot.php"]

tests/dockerfiles/Dockerfile.alpine

Lines changed: 0 additions & 32 deletions
This file was deleted.

tests/dockerfiles/deepbind.patch

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
From e87144e1a87789dbb1b53957de1668086100e808 Mon Sep 17 00:00:00 2001
2+
From: Daniil Gentili <daniil@daniil.it>
3+
Date: Wed, 13 Nov 2024 12:24:29 +0000
4+
Subject: [PATCH] Add --enable-rtld-deepbind configure flag
5+
6+
---
7+
Zend/zend_portability.h | 2 +-
8+
configure.ac | 17 +++++++++++++++++
9+
2 files changed, 18 insertions(+), 1 deletion(-)
10+
11+
diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h
12+
index 9ab46f9b32cfe..1efc15fb6386c 100644
13+
--- a/Zend/zend_portability.h
14+
+++ b/Zend/zend_portability.h
15+
@@ -164,7 +164,7 @@
16+
17+
# if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
18+
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
19+
-# elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(memory_sanitizer)
20+
+# elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(memory_sanitizer) && defined(PHP_USE_RTLD_DEEPBIND)
21+
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
22+
# else
23+
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
24+
diff --git a/configure.ac b/configure.ac
25+
index 01d9ded69b920..137f7dae8c3a9 100644
26+
--- a/configure.ac
27+
+++ b/configure.ac
28+
@@ -868,6 +868,23 @@ AS_VAR_IF([PHP_RTLD_NOW], [yes],
29+
[Define to 1 if 'dlopen()' uses the 'RTLD_NOW' mode flag instead of
30+
'RTLD_LAZY'.])])
31+
32+
+if test "$PHP_SAPI" = "apache2handler"; then
33+
+ PHP_RTLD_DEEPBIND_DEFAULT=yes
34+
+else
35+
+ PHP_RTLD_DEEPBIND_DEFAULT=no
36+
+fi
37+
+
38+
+PHP_ARG_ENABLE([rtld-deepbind],
39+
+ [whether to dlopen extensions with RTLD_DEEPBIND],
40+
+ [AS_HELP_STRING([--enable-rtld-deepbind],
41+
+ [Use dlopen with RTLD_DEEPBIND])],
42+
+ [$PHP_RTLD_DEEPBIND_DEFAULT],
43+
+ [$PHP_RTLD_DEEPBIND_DEFAULT])
44+
+
45+
+if test "$PHP_RTLD_DEEPBIND" = "yes"; then
46+
+ AC_DEFINE(PHP_USE_RTLD_DEEPBIND, 1, [ Use dlopen with RTLD_DEEPBIND ])
47+
+fi
48+
+
49+
PHP_ARG_WITH([layout],
50+
[layout of installed files],
51+
[AS_HELP_STRING([--with-layout=TYPE],

0 commit comments

Comments
 (0)