|
| 1 | +# https://docs.ghost.org/faq/node-versions/ |
| 2 | +# https://github.com/nodejs/Release (looking for "LTS") |
| 3 | +# https://github.com/TryGhost/Ghost/blob/v4.1.2/package.json#L38 |
| 4 | +FROM node:16-bullseye-slim |
| 5 | + |
| 6 | +# grab gosu for easy step-down from root |
| 7 | +# https://github.com/tianon/gosu/releases |
| 8 | +ENV GOSU_VERSION 1.12 |
| 9 | +RUN set -eux; \ |
| 10 | +# save list of currently installed packages for later so we can clean up |
| 11 | + savedAptMark="$(apt-mark showmanual)"; \ |
| 12 | + apt-get update; \ |
| 13 | + apt-get install -y --no-install-recommends ca-certificates dirmngr gnupg wget; \ |
| 14 | + rm -rf /var/lib/apt/lists/*; \ |
| 15 | + \ |
| 16 | + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ |
| 17 | + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ |
| 18 | + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ |
| 19 | + \ |
| 20 | +# verify the signature |
| 21 | + export GNUPGHOME="$(mktemp -d)"; \ |
| 22 | + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ |
| 23 | + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ |
| 24 | + command -v gpgconf && gpgconf --kill all || :; \ |
| 25 | + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ |
| 26 | + \ |
| 27 | +# clean up fetch dependencies |
| 28 | + apt-mark auto '.*' > /dev/null; \ |
| 29 | + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ |
| 30 | + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ |
| 31 | + \ |
| 32 | + chmod +x /usr/local/bin/gosu; \ |
| 33 | +# verify that the binary works |
| 34 | + gosu --version; \ |
| 35 | + gosu nobody true |
| 36 | + |
| 37 | +ENV NODE_ENV production |
| 38 | + |
| 39 | +ENV GHOST_CLI_VERSION 1.21.0 |
| 40 | +RUN set -eux; \ |
| 41 | + npm install -g "ghost-cli@$GHOST_CLI_VERSION"; \ |
| 42 | + npm cache clean --force |
| 43 | + |
| 44 | +ENV GHOST_INSTALL /var/lib/ghost |
| 45 | +ENV GHOST_CONTENT /var/lib/ghost/content |
| 46 | + |
| 47 | +ENV GHOST_VERSION 5.0.0 |
| 48 | + |
| 49 | +RUN set -eux; \ |
| 50 | + mkdir -p "$GHOST_INSTALL"; \ |
| 51 | + chown node:node "$GHOST_INSTALL"; \ |
| 52 | + \ |
| 53 | + gosu node ghost install "$GHOST_VERSION" --db sqlite3 --no-prompt --no-stack --no-setup --dir "$GHOST_INSTALL"; \ |
| 54 | + \ |
| 55 | +# Tell Ghost to listen on all ips and not prompt for additional configuration |
| 56 | + cd "$GHOST_INSTALL"; \ |
| 57 | + gosu node ghost config --ip '::' --port 2368 --no-prompt --db sqlite3 --url http://localhost:2368 --dbpath "$GHOST_CONTENT/data/ghost.db"; \ |
| 58 | + gosu node ghost config paths.contentPath "$GHOST_CONTENT"; \ |
| 59 | + \ |
| 60 | +# make a config.json symlink for NODE_ENV=development (and sanity check that it's correct) |
| 61 | + gosu node ln -s config.production.json "$GHOST_INSTALL/config.development.json"; \ |
| 62 | + readlink -f "$GHOST_INSTALL/config.development.json"; \ |
| 63 | + \ |
| 64 | +# need to save initial content for pre-seeding empty volumes |
| 65 | + mv "$GHOST_CONTENT" "$GHOST_INSTALL/content.orig"; \ |
| 66 | + mkdir -p "$GHOST_CONTENT"; \ |
| 67 | + chown node:node "$GHOST_CONTENT"; \ |
| 68 | + chmod 1777 "$GHOST_CONTENT"; \ |
| 69 | + \ |
| 70 | +# force install "sqlite3" manually since it's an optional dependency of "ghost" |
| 71 | +# (which means that if it fails to install, like on ARM/ppc64le/s390x, the failure will be silently ignored and thus turn into a runtime error instead) |
| 72 | +# see https://github.com/TryGhost/Ghost/pull/7677 for more details |
| 73 | + cd "$GHOST_INSTALL/current"; \ |
| 74 | +# scrape the expected version of sqlite3 directly from Ghost itself |
| 75 | + sqlite3Version="$(node -p 'require("./package.json").optionalDependencies["sqlite3"]')"; \ |
| 76 | + [ -n "$sqlite3Version" ]; \ |
| 77 | + [ "$sqlite3Version" != 'undefined' ]; \ |
| 78 | + if ! gosu node yarn add "sqlite3@$sqlite3Version" --force; then \ |
| 79 | +# must be some non-amd64 architecture pre-built binaries aren't published for, so let's install some build deps and do-it-all-over-again |
| 80 | + savedAptMark="$(apt-mark showmanual)"; \ |
| 81 | + apt-get update; \ |
| 82 | + apt-get install -y --no-install-recommends g++ gcc libc-dev libvips-dev make python2; \ |
| 83 | + rm -rf /var/lib/apt/lists/*; \ |
| 84 | + \ |
| 85 | + npm_config_python='python2' gosu node yarn add "sqlite3@$sqlite3Version" --force --build-from-source; \ |
| 86 | + \ |
| 87 | + apt-mark showmanual | xargs apt-mark auto > /dev/null; \ |
| 88 | + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ |
| 89 | + apt-get purge -y --auto-remove; \ |
| 90 | + fi; \ |
| 91 | + \ |
| 92 | + gosu node yarn cache clean; \ |
| 93 | + gosu node npm cache clean --force; \ |
| 94 | + npm cache clean --force; \ |
| 95 | + rm -rv /tmp/yarn* /tmp/v8* |
| 96 | + |
| 97 | +WORKDIR $GHOST_INSTALL |
| 98 | +VOLUME $GHOST_CONTENT |
| 99 | + |
| 100 | +COPY docker-entrypoint.sh /usr/local/bin |
| 101 | +ENTRYPOINT ["docker-entrypoint.sh"] |
| 102 | + |
| 103 | +EXPOSE 2368 |
| 104 | +CMD ["node", "current/index.js"] |
0 commit comments