From 6b96f224ae0feb07d4ccdd35c1c32e5f804b8f8f Mon Sep 17 00:00:00 2001 From: Joakim Fors Date: Thu, 18 Jun 2020 12:40:08 +0200 Subject: [PATCH 1/6] Streamline Dockerfile for caching and size Move package installation to top of file to enable layer caching in Docker. Use multi stage builds to reduce final image size. Ignore everything but essential files when creating Docker build context. --- .dockerignore | 13 +++++---- Dockerfile | 73 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/.dockerignore b/.dockerignore index fee5276..2523191 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,6 @@ -.git -docs/_build -node_modules -test_data -light -config.json -*.mbtiles +* +!src +!public +!package.json +!package-lock.json +!run.sh diff --git a/Dockerfile b/Dockerfile index 4bc76b7..f51c688 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,30 +1,59 @@ -FROM node:10-stretch +FROM node:10-buster AS builder + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get -qq update \ + && apt-get -y --no-install-recommends install \ + apt-transport-https \ + curl \ + unzip \ + build-essential \ + python \ + libcairo2-dev \ + libgles2-mesa-dev \ + libgbm-dev \ + libllvm7 \ + libprotobuf-dev \ + libxxf86vm-dev \ + xvfb \ + x11-utils \ + && apt-get -y --purge autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +#RUN mkdir -p /usr/src/app +COPY / /usr/src/app + +ENV NODE_ENV="production" + +RUN cd /usr/src/app && npm install --production + + +FROM node:10-buster-slim AS final + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get -qq update \ + && apt-get -y --no-install-recommends install \ + curl \ + libcairo2 \ + libgles2-mesa \ + libegl1 \ + libprotobuf17 \ + libxxf86vm1 \ + xvfb \ + x11-utils \ + && apt-get -y --purge autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/src/app /usr/src/app ENV NODE_ENV="production" ENV CHOKIDAR_USEPOLLING=1 ENV CHOKIDAR_INTERVAL=500 + VOLUME /data WORKDIR /data + EXPOSE 80 -ENTRYPOINT ["/bin/bash", "/usr/src/app/run.sh"] -RUN apt-get -qq update \ -&& DEBIAN_FRONTEND=noninteractive apt-get -y install \ - apt-transport-https \ - curl \ - unzip \ - build-essential \ - python \ - libcairo2-dev \ - libgles2-mesa-dev \ - libgbm-dev \ - libllvm3.9 \ - libprotobuf-dev \ - libxxf86vm-dev \ - xvfb \ - x11-utils \ -&& apt-get clean - -RUN mkdir -p /usr/src/app -COPY / /usr/src/app -RUN cd /usr/src/app && npm install --production +ENTRYPOINT ["/usr/src/app/run.sh"] From 16de5be6735090999ff9dc5b16a9468b0a4d0a36 Mon Sep 17 00:00:00 2001 From: Joakim Fors Date: Thu, 18 Jun 2020 14:23:59 +0200 Subject: [PATCH 2/6] Use simplified entrypoint script --- .dockerignore | 2 +- Dockerfile | 8 +++++--- docker-entrypoint.sh | 11 +++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100755 docker-entrypoint.sh diff --git a/.dockerignore b/.dockerignore index 2523191..b849c8a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,4 +3,4 @@ !public !package.json !package-lock.json -!run.sh +!docker-entrypoint.sh diff --git a/Dockerfile b/Dockerfile index f51c688..b624db3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,12 +40,12 @@ RUN export DEBIAN_FRONTEND=noninteractive \ libprotobuf17 \ libxxf86vm1 \ xvfb \ - x11-utils \ + xauth \ && apt-get -y --purge autoremove \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -COPY --from=builder /usr/src/app /usr/src/app +COPY --from=builder /usr/src/app /app ENV NODE_ENV="production" ENV CHOKIDAR_USEPOLLING=1 @@ -56,4 +56,6 @@ WORKDIR /data EXPOSE 80 -ENTRYPOINT ["/usr/src/app/run.sh"] +ENTRYPOINT ["/app/docker-entrypoint.sh"] + +CMD ["-p", "80"] diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000..599800e --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +if ! which -- "${1}"; then + # first arg is not an executable + xvfb-run --server-args="-screen 0 1024x768x24" -- node /app/ "$@" + exit $? +fi + +exec "$@" From 1d216489695e85ebe5155b74f6ea54eb0dfe99a6 Mon Sep 17 00:00:00 2001 From: Joakim Fors Date: Thu, 18 Jun 2020 14:24:35 +0200 Subject: [PATCH 3/6] Run as node user instead of root --- Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index b624db3..f517b73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,8 +54,10 @@ ENV CHOKIDAR_INTERVAL=500 VOLUME /data WORKDIR /data -EXPOSE 80 +EXPOSE 8000 + +USER node:node ENTRYPOINT ["/app/docker-entrypoint.sh"] -CMD ["-p", "80"] +CMD ["-p", "8000"] From 9f59f670875be265011bb66b20da58dbc2ff0a42 Mon Sep 17 00:00:00 2001 From: Joakim Fors Date: Thu, 18 Jun 2020 14:24:56 +0200 Subject: [PATCH 4/6] Clean up dependencies --- Dockerfile | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index f517b73..6e03a0e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,15 +13,11 @@ RUN export DEBIAN_FRONTEND=noninteractive \ libgbm-dev \ libllvm7 \ libprotobuf-dev \ - libxxf86vm-dev \ - xvfb \ - x11-utils \ && apt-get -y --purge autoremove \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -#RUN mkdir -p /usr/src/app -COPY / /usr/src/app +COPY . /usr/src/app ENV NODE_ENV="production" @@ -33,12 +29,8 @@ FROM node:10-buster-slim AS final RUN export DEBIAN_FRONTEND=noninteractive \ && apt-get -qq update \ && apt-get -y --no-install-recommends install \ - curl \ - libcairo2 \ libgles2-mesa \ libegl1 \ - libprotobuf17 \ - libxxf86vm1 \ xvfb \ xauth \ && apt-get -y --purge autoremove \ From 8d2ddd8f95c1e8f41a6563e94eb0cd6e51491330 Mon Sep 17 00:00:00 2001 From: Joakim Fors Date: Fri, 26 Jun 2020 20:13:57 +0200 Subject: [PATCH 5/6] Use automatic server number --- docker-entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 599800e..097b194 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -4,7 +4,7 @@ set -e if ! which -- "${1}"; then # first arg is not an executable - xvfb-run --server-args="-screen 0 1024x768x24" -- node /app/ "$@" + xvfb-run -a --server-args="-screen 0 1024x768x24" -- node /app/ "$@" exit $? fi From 6b3f557b1f4f2dde31f73e252eb8f1fc011233fb Mon Sep 17 00:00:00 2001 From: Joakim Fors Date: Fri, 4 Dec 2020 20:57:06 +0100 Subject: [PATCH 6/6] Gracefully handle signals from Docker or terminal Start Xvfb wrapper in background and wait for the process to complete. Because wait exits immediately when a signal for which a trap has been set, and the signal handler is executed directly after that, we need to wait again for the background processes to actually finish before exiting. The signal handler catches INT and TERM and forwards them to the node process. The return value from the first wait is stored and sent as exit value. --- docker-entrypoint.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 097b194..8b7984c 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -2,10 +2,22 @@ set -e +handle() { + SIGNAL=$(( $? - 128 )) + echo "Caught signal ${SIGNAL}, stopping gracefully" + kill -s ${SIGNAL} $(pidof node) 2>/dev/null +} + +trap handle INT TERM + if ! which -- "${1}"; then # first arg is not an executable - xvfb-run -a --server-args="-screen 0 1024x768x24" -- node /app/ "$@" - exit $? + xvfb-run -a --server-args="-screen 0 1024x768x24" -- node /app/ "$@" & + # Wait exits immediately on signals which have traps set. Store return value and wait + # again for all jobs to actually complete before continuing. + wait $! || RETVAL=$? + wait + exit ${RETVAL} fi exec "$@"