Skip to content

Commit

Permalink
👷 build: optimize image size under glibc env (#4025)
Browse files Browse the repository at this point in the history
* 👷 build: optimize image size under `glibc` env

* 👷 build: add `startServer.js` as server launcher

* 🐛 fix: `PROXY_URL` missing

* 🔨 chore: exit if DB migration failed

* 🔨 chore: allow resolve ipv6 address

* 🔨 chore: rollback changes, cleanup code

* 🔨 chore: improve console log

* 🔨 chore: improve error print

* 👷 build: add `isValidSSL` function to check SSL cert

* 🔨 chore: handle `CERT_HAS_EXPIRED` error

* 🔨 chore: cleanup code

* 🔨 chore: improve console log

* 👷 build: check oss & auth issuer ssl connection before running

* 🔨 chore: improve console log

* 🔨 chore: change `SSL` to `TLS`

* 🐛 fix: fix `443` port not display in logs

* 🔨 chore: improve console output

* 🐛 fix: fix error catch

* 🔨 chore: handle corner case

* 👷 build: support self-signed SSL cert, switch to system-wide CA cert

* 🔨 chore: handle `UNABLE_TO_GET_ISSUER_CERT_LOCALLY` error

* 🔨 chore: handle when `*_ISSUER` not existed

* 🔨 chore: handle non-https protocol, skip TLS checking

* 🔨 chore: improve console log

* 🐛 fix: fix proxychains logs not available when host is ip addr

* 👷 build: add DNS server self-check support, split DNS resolve function

* 🔨 chore: improve console.log

* 🔨 chore: print DNS server before db migration

* 🔨 chore: update `isValidIP` & `resolveHostIP` function, ready for IPv6

* 🐛 fix: fix error handle

* 👷 build: set `ENTRYPOINT` to `/bin/node`

* 👷 build: set full path for `proxychains` & `node`, ready for distroless

* 👷 build: pin node LTS version to 20
  • Loading branch information
hezhijie0327 committed Sep 27, 2024
1 parent adb78c2 commit 7eecb23
Show file tree
Hide file tree
Showing 3 changed files with 253 additions and 102 deletions.
85 changes: 36 additions & 49 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Base image for all the stages
## Base image for all building stages
FROM node:20-slim AS base

ARG USE_CN_MIRROR
Expand All @@ -10,19 +10,22 @@ RUN \
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"; \
fi \
# Add required package & update base package
# Add required package
&& apt update \
&& apt install busybox proxychains-ng -qy \
&& apt full-upgrade -qy \
&& apt autoremove -qy --purge \
&& apt clean -qy \
# Configure BusyBox
&& busybox --install -s \
# Add nextjs:nodejs to run the app
&& addgroup --system --gid 1001 nodejs \
&& adduser --system --home "/app" --gid 1001 -uid 1001 nextjs \
# Set permission for nextjs:nodejs
&& chown -R nextjs:nodejs "/etc/proxychains4.conf" \
&& apt install ca-certificates proxychains-ng -qy \
# Prepare required package to distroless
&& mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib \
# Copy proxychains to distroless
&& cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 \
&& cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 \
&& cp /usr/bin/proxychains4 /distroless/bin/proxychains \
&& cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf \
# Copy node to distroless
&& cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 \
&& cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 \
&& cp /usr/local/bin/node /distroless/bin/node \
# Copy CA certificates to distroless
&& cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt \
# Cleanup temp files
&& rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*

Expand Down Expand Up @@ -80,7 +83,9 @@ COPY . .
RUN npm run build:docker

## Application image, copy all the files for production
FROM scratch AS app
FROM busybox:latest AS app

COPY --from=base /distroless/ /

COPY --from=builder /app/public /app/public

Expand All @@ -90,13 +95,25 @@ COPY --from=builder /app/.next/standalone /app/
COPY --from=builder /app/.next/static /app/.next/static
COPY --from=builder /deps/node_modules/.pnpm /app/node_modules/.pnpm

# Copy server launcher
COPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js

RUN \
# Add nextjs:nodejs to run the app
addgroup -S -g 1001 nodejs \
&& adduser -D -G nodejs -H -S -h /app -u 1001 nextjs \
# Set permission for nextjs:nodejs
&& chown -R nextjs:nodejs /app /etc/proxychains4.conf

## Production image, copy all the files and run next
FROM base
FROM scratch

# Copy all the files from app, set the correct permission for prerender cache
COPY --from=app --chown=nextjs:nodejs /app /app
COPY --from=app / /

ENV NODE_ENV="production" \
NODE_OPTIONS="--use-openssl-ca" \
NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt"
NODE_TLS_REJECT_UNAUTHORIZED=""

# set hostname to localhost
Expand Down Expand Up @@ -176,36 +193,6 @@ USER nextjs

EXPOSE 3210/tcp

CMD \
if [ -n "$PROXY_URL" ]; then \
# Set regex for IPv4
IP_REGEX="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$"; \
# Set proxychains command
PROXYCHAINS="proxychains -q"; \
# Parse the proxy URL
host_with_port="${PROXY_URL#*//}"; \
host="${host_with_port%%:*}"; \
port="${PROXY_URL##*:}"; \
protocol="${PROXY_URL%%://*}"; \
# Resolve to IP address if the host is a domain
if ! [[ "$host" =~ "$IP_REGEX" ]]; then \
nslookup=$(nslookup -q="A" "$host" | tail -n +3 | grep 'Address:'); \
if [ -n "$nslookup" ]; then \
host=$(echo "$nslookup" | tail -n 1 | awk '{print $2}'); \
fi; \
fi; \
# Generate proxychains configuration file
printf "%s\n" \
'localnet 127.0.0.0/255.0.0.0' \
'localnet ::1/128' \
'proxy_dns' \
'remote_dns_subnet 224' \
'strict_chain' \
'tcp_connect_time_out 8000' \
'tcp_read_time_out 15000' \
'[ProxyList]' \
"$protocol $host $port" \
> "/etc/proxychains4.conf"; \
fi; \
# Run the server
${PROXYCHAINS} node "/app/server.js";
ENTRYPOINT ["/bin/node"]

CMD ["/app/startServer.js"]
89 changes: 36 additions & 53 deletions Dockerfile.database
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Base image for all the stages
## Base image for all building stages
FROM node:20-slim AS base

ARG USE_CN_MIRROR
Expand All @@ -10,19 +10,22 @@ RUN \
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"; \
fi \
# Add required package & update base package
# Add required package
&& apt update \
&& apt install busybox proxychains-ng -qy \
&& apt full-upgrade -qy \
&& apt autoremove -qy --purge \
&& apt clean -qy \
# Configure BusyBox
&& busybox --install -s \
# Add nextjs:nodejs to run the app
&& addgroup --system --gid 1001 nodejs \
&& adduser --system --home "/app" --gid 1001 -uid 1001 nextjs \
# Set permission for nextjs:nodejs
&& chown -R nextjs:nodejs "/etc/proxychains4.conf" \
&& apt install ca-certificates proxychains-ng -qy \
# Prepare required package to distroless
&& mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib \
# Copy proxychains to distroless
&& cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 \
&& cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 \
&& cp /usr/bin/proxychains4 /distroless/bin/proxychains \
&& cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf \
# Copy node to distroless
&& cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 \
&& cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 \
&& cp /usr/local/bin/node /distroless/bin/node \
# Copy CA certificates to distroless
&& cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt \
# Cleanup temp files
&& rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*

Expand Down Expand Up @@ -84,7 +87,9 @@ COPY . .
RUN npm run build:docker

## Application image, copy all the files for production
FROM scratch AS app
FROM busybox:latest AS app

COPY --from=base /distroless/ /

COPY --from=builder /app/public /app/public

Expand All @@ -103,13 +108,25 @@ COPY --from=builder /app/src/database/server/migrations /app/migrations
COPY --from=builder /app/scripts/migrateServerDB/docker.cjs /app/docker.cjs
COPY --from=builder /app/scripts/migrateServerDB/errorHint.js /app/errorHint.js

# Copy server launcher
COPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js

RUN \
# Add nextjs:nodejs to run the app
addgroup -S -g 1001 nodejs \
&& adduser -D -G nodejs -H -S -h /app -u 1001 nextjs \
# Set permission for nextjs:nodejs
&& chown -R nextjs:nodejs /app /etc/proxychains4.conf

## Production image, copy all the files and run next
FROM base
FROM scratch

# Copy all the files from app, set the correct permission for prerender cache
COPY --from=app --chown=nextjs:nodejs /app /app
COPY --from=app / /

ENV NODE_ENV="production" \
NODE_OPTIONS="--use-openssl-ca" \
NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt"
NODE_TLS_REJECT_UNAUTHORIZED=""

# set hostname to localhost
Expand Down Expand Up @@ -208,40 +225,6 @@ USER nextjs

EXPOSE 3210/tcp

CMD \
if [ -n "$PROXY_URL" ]; then \
# Set regex for IPv4
IP_REGEX="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$"; \
# Set proxychains command
PROXYCHAINS="proxychains -q"; \
# Parse the proxy URL
host_with_port="${PROXY_URL#*//}"; \
host="${host_with_port%%:*}"; \
port="${PROXY_URL##*:}"; \
protocol="${PROXY_URL%%://*}"; \
# Resolve to IP address if the host is a domain
if ! [[ "$host" =~ "$IP_REGEX" ]]; then \
nslookup=$(nslookup -q="A" "$host" | tail -n +3 | grep 'Address:'); \
if [ -n "$nslookup" ]; then \
host=$(echo "$nslookup" | tail -n 1 | awk '{print $2}'); \
fi; \
fi; \
# Generate proxychains configuration file
printf "%s\n" \
'localnet 127.0.0.0/255.0.0.0' \
'localnet ::1/128' \
'proxy_dns' \
'remote_dns_subnet 224' \
'strict_chain' \
'tcp_connect_time_out 8000' \
'tcp_read_time_out 15000' \
'[ProxyList]' \
"$protocol $host $port" \
> "/etc/proxychains4.conf"; \
fi; \
# Run migration
node "/app/docker.cjs"; \
if [ "$?" -eq "0" ]; then \
# Run the server
${PROXYCHAINS} node "/app/server.js"; \
fi;
ENTRYPOINT ["/bin/node"]

CMD ["/app/startServer.js"]
Loading

0 comments on commit 7eecb23

Please sign in to comment.