diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 365afcd93013074816b0acd3fd3f911ea8935478..bbb1fb26792cb68260355ee908515fade6c213c0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ variables: - export DISCOURSE_MAJOR=`echo $DISCOURSE_VERSION | cut -d"." -f1-3` - echo $DISCOURSE_MAJOR - echo $DISCOURSE_VERSION - - /kaniko/executor --context . ${DESTINATION} --build-arg DISCOURSE_VERSION=$DISCOURSE_VERSION + - /kaniko/executor --single-snapshot --context . ${DESTINATION} --build-arg DISCOURSE_VERSION=$DISCOURSE_VERSION except: - master diff --git a/Dockerfile b/Dockerfile index 7ec8073407900260134678a90ceadd4e4e744af4..ad46755db6bd849695a4585dc4ad93cb209aa85d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,48 +1,125 @@ -ARG from=discourse/base -ARG tag=slim -ARG DISCOURSE_VERSION=test-passed +FROM debian:bullseye-slim -FROM $from:$tag - -ENV RAILS_ENV=production \ - DISCOURSE_SERVE_STATIC_ASSETS=true \ - EMBER_CLI_COMPILE_DONE=1 \ - EMBER_CLI_PROD_ASSETS=1 \ - RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 \ +# slim https://github.com/discourse/discourse_docker/blob/main/image/base/slim.Dockerfile#L5 +ENV RUBY_ALLOCATOR=/usr/lib/libjemalloc.so.1 \ + RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:$PATH \ + LEFTHOOK=0 +# release https://github.com/discourse/discourse_docker/blob/main/image/base/release.Dockerfile#L6 +ENV RAILS_ENV=production +# web template https://github.com/discourse/discourse_docker/blob/main/templates/web.template.yml#L1 +ENV DISCOURSE_SERVE_STATIC_ASSETS=true \ + SKIP_EMBER_CLI_COMPILE=1 \ RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000 \ RUBY_GC_HEAP_INIT_SLOTS=400000 \ - RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5 \ - RUBY_GC_MALLOC_LIMIT=90000000 + RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5 +#LABEL maintainer="Sam Saffron \"https://twitter.com/samsaffron\"" -# jq needed to create kubernetes CM -RUN apt-get update && apt-get install -y jq +RUN echo 'deb http://deb.debian.org/debian bullseye-backports main' > /etc/apt/sources.list.d/bullseye-backports.list +RUN echo "debconf debconf/frontend select Teletype" | debconf-set-selections +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install gnupg sudo curl -WORKDIR /var/www/discourse +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y locales locales-all +ENV LC_ALL en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US.UTF-8 -RUN git config --global --add safe.directory /var/www/discourse &&\ - git remote set-branches --add origin ${DISCOURSE_VERSION} &&\ - git fetch --depth 1 origin ${DISCOURSE_VERSION} &&\ - sudo -u discourse bundle config --local deployment true &&\ - sudo -u discourse bundle config --local path ./vendor/bundle &&\ - sudo -u discourse bundle config --local without test development &&\ - sudo -u discourse bundle config --local jobs 4 && \ - sudo -u discourse bundle install &&\ - sudo -u discourse yarn install --frozen-lockfile &&\ - sudo -u discourse yarn cache clean &&\ - find /var/www/discourse/vendor/bundle -name tmp -type d -exec rm -rf {} + &&\ - chown -R discourse:discourse /var/www/discourse +RUN curl --silent --location https://deb.nodesource.com/setup_18.x | sudo bash - +RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - +RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list +RUN apt-get -y update +# install these without recommends to avoid pulling in e.g. +# X11 libraries, mailutils +RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends git jq +RUN DEBIAN_FRONTEND=noninteractive apt-get -y install autoconf build-essential ca-certificates \ + libxslt-dev libcurl4-openssl-dev \ + libssl-dev libyaml-dev libtool \ + libpcre3 libpcre3-dev zlib1g zlib1g-dev \ + libxml2-dev gawk \ + libreadline-dev libpq-dev \ + psmisc whois brotli libunwind-dev \ + libtcmalloc-minimal4 cmake \ + pngcrush pngquant ripgrep -COPY install /tmp/install +RUN cd / &&\ + apt-get clean &&\ + locale-gen en_US &&\ + DEBIAN_FRONTEND=noninteractive apt-get install -y wget nodejs yarn &&\ + npm install -g terser uglify-js pnpm + +ADD install-imagemagick /tmp/install-imagemagick +RUN /tmp/install-imagemagick + +ADD install-jemalloc /tmp/install-jemalloc +RUN /tmp/install-jemalloc + +ADD install-rust /tmp/install-rust +ADD install-ruby /tmp/install-ruby +ADD install-oxipng /tmp/install-oxipng +RUN /tmp/install-rust && /tmp/install-ruby && /tmp/install-oxipng && rustup self uninstall -y + +RUN echo 'gem: --no-document' >> /usr/local/etc/gemrc &&\ + gem update --system + +# This tool allows us to disable huge page support for our current process +# since the flag is preserved through forks and execs it can be used on any +# process +ADD thpoff.c /src/thpoff.c +RUN gcc -o /usr/local/sbin/thpoff /src/thpoff.c && rm /src/thpoff.c + +# clean up for docker squash +RUN rm -fr /usr/share/man &&\ + rm -fr /usr/share/doc &&\ + rm -fr /usr/share/vim/vim74/doc &&\ + rm -fr /usr/share/vim/vim74/lang &&\ + rm -fr /usr/share/vim/vim74/spell/en* &&\ + rm -fr /usr/share/vim/vim74/tutor &&\ + rm -fr /usr/local/share/doc &&\ + rm -fr /usr/local/share/ri &&\ + rm -fr /usr/local/share/ruby-build &&\ + rm -fr /var/lib/apt/lists/* &&\ + rm -fr /root/.gem &&\ + rm -fr /root/.npm &&\ + rm -fr /tmp/* + +# this can probably be done, but I worry that people changing PG locales will have issues +# cd /usr/share/locale && rm -fr `ls -d */ | grep -v en` + +# this is required for aarch64 which uses buildx +# see https://github.com/docker/buildx/issues/150 +RUN rm -f /etc/service + +ARG DISCOURSE_VERSION + +# Discourse specific bits +RUN useradd discourse -s /bin/bash -m -U &&\ + install -dm 0755 -o discourse -g discourse /var/www/discourse &&\ + sudo -u discourse curl -s -L https://github.com/discourse/discourse/archive/refs/tags/${DISCOURSE_VERSION}.tar.gz | tar xvz -C /var/www/discourse --strip-components 1 &&\ + gem install bundler --conservative -v $(awk '/BUNDLED WITH/ { getline; gsub(/ /,""); print $0 }' /var/www/discourse/Gemfile.lock) &&\ + chown -R discourse:discourse /var/www/discourse USER discourse +WORKDIR /var/www/discourse + +RUN bundle config --local deployment true &&\ + bundle config --local path ./vendor/bundle &&\ + bundle config --local without test development &&\ + bundle config --local jobs 4 && \ + bundle install &&\ + yarn install --frozen-lockfile &&\ + yarn cache clean &&\ + find /var/www/discourse/vendor/bundle -name tmp -type d -exec rm -rf {} + + +COPY install /tmp/install RUN cd /var/www/discourse/plugins \ && for plugin in $(cat /tmp/install/plugin-list); do \ - git clone $plugin; \ + git clone --depth 1 $plugin; \ done -RUN cd app/assets/javascripts/discourse && \ +RUN cd app/assets/javascripts/discourse && \ /var/www/discourse/app/assets/javascripts/node_modules/.bin/ember build -prod -CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"] +CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"] \ No newline at end of file diff --git a/install-imagemagick b/install-imagemagick new file mode 100755 index 0000000000000000000000000000000000000000..911e719e618052fcebadae26281f94bb567ef138 --- /dev/null +++ b/install-imagemagick @@ -0,0 +1,72 @@ +#!/bin/bash +set -e + +# version check: https://github.com/ImageMagick/ImageMagick/releases +IMAGE_MAGICK_VERSION="7.1.0-62" +IMAGE_MAGICK_HASH="d282117bc6d0e91ad1ad685d096623b96ed8e229f911c891d83277b350ef884a" + +# We use debian, but GitHub CI is stuck on Ubuntu Bionic, so this must be compatible with both +LIBJPEGTURBO=$(cat /etc/issue | grep -qi Debian && echo 'libjpeg62-turbo libjpeg62-turbo-dev' || echo 'libjpeg-turbo8 libjpeg-turbo8-dev') + +# Ubuntu 22.04/22.10 doesn't have libwebp6 +LIBWEBP=$(cat /etc/issue | grep -qi 'Ubuntu 22' && echo 'libwebp7' || echo 'libwebp6') + +PREFIX=/usr/local +WDIR=/tmp/imagemagick + +# Install build deps +apt -y -q remove imagemagick +apt -y -q install git make gcc pkg-config autoconf curl g++ yasm cmake \ + libde265-0 libde265-dev ${LIBJPEGTURBO} x265 libx265-dev libtool \ + libpng16-16 libpng-dev ${LIBJPEGTURBO} ${LIBWEBP} libwebp-dev libgomp1 \ + libwebpmux3 libwebpdemux2 ghostscript libxml2-dev libxml2-utils librsvg2-dev \ + libltdl7-dev libbz2-dev gsfonts libtiff-dev libfreetype6-dev libjpeg-dev + +# Ubuntu doesn't like `bullseye-backports` +if cat /etc/issue | grep -qi 'Ubuntu 22'; then + apt -y install libheif1 libaom-dev libheif-dev +else + # Use backports instead of compiling it + apt -y -q install -t bullseye-backports libheif1 libaom-dev libheif-dev +fi + +mkdir -p $WDIR +cd $WDIR + +# Build and install ImageMagick +wget -q -O $WDIR/ImageMagick.tar.gz "https://github.com/ImageMagick/ImageMagick/archive/$IMAGE_MAGICK_VERSION.tar.gz" +sha256sum $WDIR/ImageMagick.tar.gz +echo "$IMAGE_MAGICK_HASH $WDIR/ImageMagick.tar.gz" | sha256sum -c +IMDIR=$WDIR/$(tar tzf $WDIR/ImageMagick.tar.gz --wildcards "ImageMagick-*/configure" |cut -d/ -f1) +tar zxf $WDIR/ImageMagick.tar.gz -C $WDIR +cd $IMDIR +PKG_CONF_LIBDIR=$PREFIX/lib LDFLAGS=-L$PREFIX/lib CFLAGS=-I$PREFIX/include ./configure \ + --prefix=$PREFIX \ + --enable-static \ + --enable-bounds-checking \ + --enable-hdri \ + --enable-hugepages \ + --with-threads \ + --with-modules \ + --with-quantum-depth=16 \ + --without-magick-plus-plus \ + --with-bzlib \ + --with-zlib \ + --without-autotrace \ + --with-freetype \ + --with-jpeg \ + --without-lcms \ + --with-lzma \ + --with-png \ + --with-tiff \ + --with-heic \ + --with-rsvg \ + --with-webp +make all && make install + +cd $HOME +rm -rf $WDIR +ldconfig /usr/local/lib + +# Validate ImageMagick install +test $(convert -version | grep -o -e png -e tiff -e jpeg -e freetype -e heic -e webp | wc -l) -eq 6 diff --git a/install-jemalloc b/install-jemalloc new file mode 100755 index 0000000000000000000000000000000000000000..b07597874abbd8c986e711bf41f3562d803c993e --- /dev/null +++ b/install-jemalloc @@ -0,0 +1,26 @@ +#!/bin/bash +set -e + +# version check: https://github.com/jemalloc/jemalloc/releases + +# jemalloc stable +mkdir /jemalloc-stable +cd /jemalloc-stable + +wget -q https://github.com/jemalloc/jemalloc/releases/download/3.6.0/jemalloc-3.6.0.tar.bz2 +sha256sum jemalloc-3.6.0.tar.bz2 +echo "e16c2159dd3c81ca2dc3b5c9ef0d43e1f2f45b04548f42db12e7c12d7bdf84fe jemalloc-3.6.0.tar.bz2" | sha256sum -c +tar --strip-components=1 -xjf jemalloc-3.6.0.tar.bz2 +./configure --prefix=/usr && make && make install +cd / && rm -rf /jemalloc-stable + +# jemalloc new +mkdir /jemalloc-new +cd /jemalloc-new + +wget -q https://github.com/jemalloc/jemalloc/releases/download/5.3.0/jemalloc-5.3.0.tar.bz2 +sha256sum jemalloc-5.3.0.tar.bz2 +echo "2db82d1e7119df3e71b7640219b6dfe84789bc0537983c3b7ac4f7189aecfeaa jemalloc-5.3.0.tar.bz2" | sha256sum -c +tar --strip-components=1 -xjf jemalloc-5.3.0.tar.bz2 +./configure --prefix=/usr --with-install-suffix=5.3.0 && make build_lib && make install_lib +cd / && rm -rf /jemalloc-new diff --git a/install-oxipng b/install-oxipng new file mode 100755 index 0000000000000000000000000000000000000000..a6933ab6dde2a3b2d404c1ed44ec419420a0a644 --- /dev/null +++ b/install-oxipng @@ -0,0 +1,24 @@ +#!/bin/bash +set -e + +# version check: https://github.com/shssoichiro/oxipng/releases +OXIPNG_VERSION="8.0.0" +OXIPNG_HASH="ef96d6340e70900de0a38ace8f5f20878f6c256b18b0c59cd87f2b515437b87b" +OXIPNG_ARCHIVE="v${OXIPNG_VERSION}.tar.gz" +OXIPNG_DIR="oxipng-${OXIPNG_VERSION}" + +# Install other deps +apt-get -y install advancecomp jhead jpegoptim libjpeg-turbo-progs optipng + +cd /tmp +wget -q https://github.com/shssoichiro/oxipng/archive/refs/tags/${OXIPNG_ARCHIVE} +sha256sum ${OXIPNG_ARCHIVE} +echo "${OXIPNG_HASH} ${OXIPNG_ARCHIVE}" | sha256sum -c + +tar -zxf ${OXIPNG_ARCHIVE} +cd ${OXIPNG_DIR} + +CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse /usr/local/cargo/bin/cargo build --release +cp target/release/oxipng /usr/local/bin + +cd / && rm -fr /tmp/${OXIPNG_DIR} diff --git a/install-ruby b/install-ruby new file mode 100755 index 0000000000000000000000000000000000000000..4be5a5f1f4978b616046138f9eeb66a4278fab7b --- /dev/null +++ b/install-ruby @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +RUBY_VERSION="3.2.2" +export CONFIGURE_OPTS="--enable-yjit" + +apt-get -y install --no-install-recommends ruby bison libffi-dev + +mkdir /src +git -C /src clone https://github.com/rbenv/ruby-build.git +cd /src/ruby-build && ./install.sh +cd / && rm -fr /src + +ruby-build ${RUBY_VERSION} /usr/local + +apt-get -y purge ruby diff --git a/install-rust b/install-rust new file mode 100755 index 0000000000000000000000000000000000000000..b452637813285cd7cfb3f3d9747c666860b5037d --- /dev/null +++ b/install-rust @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +# see https://github.com/rust-lang/docker-rust/blob/master/Dockerfile-debian.template +export RUSTUP_HOME=/usr/local/rustup +export CARGO_HOME=/usr/local/cargo +export PATH=/usr/local/cargo/bin:$PATH +export RUST_VERSION=1.68.0 +export RUSTUP_VERSION=1.25.2 + +dpkgArch="$(dpkg --print-architecture)" + +case "${dpkgArch##*-}" in + amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='bb31eaf643926b2ee9f4d8d6fc0e2835e03c0a60f34d324048aa194f0b29a71c' ;; + armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='6626b90205d7fe7058754c8e993b7efd91dedc6833a11a225b296b7c2941194f' ;; + arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='4ccaa7de6b8be1569f6b764acc28e84f5eca342f5162cd5c810891bff7ed7f74' ;; + i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='34392b53a25c56435b411d3e575b63aab962034dd1409ba405e708610c829607' ;; + *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; +esac + +url="https://static.rust-lang.org/rustup/archive/${RUSTUP_VERSION}/${rustArch}/rustup-init" +wget "$url" +echo "${rustupSha256} *rustup-init" | sha256sum -c - +chmod +x rustup-init +./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch} +rm rustup-init +chmod -R a+w $RUSTUP_HOME $CARGO_HOME +rustup --version +cargo --version +rustc --version diff --git a/thpoff.c b/thpoff.c new file mode 100644 index 0000000000000000000000000000000000000000..31953192d21e8af3b21222f20c1935f5c7d6e02e --- /dev/null +++ b/thpoff.c @@ -0,0 +1,39 @@ +// PUBLIC DOMAIN CODE +// +// A tiny program that disable transparent huge pages on arbitrary processes +// thpoff echo 1 : will run echo 1 with SET_THP_DISABLE true on the process +#include <stdio.h> +#include <sys/prctl.h> +#include <unistd.h> +#include <errno.h> + +int main( int argc, char **argv) { + if (argc < 2) { + fprintf(stderr, "ERROR: expecting at least 1 argument!\n"); + return -1; + } + prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0); + + char* newargv[argc]; + int i; + + newargv[argc-1] = NULL; + for (i=1; i<argc; i++) { + newargv[i-1] = argv[i]; + } + + execvp(argv[1], newargv); + + if (errno == ENOENT) { + fprintf(stderr, "ERROR: file not found\n"); + return -1; + } else if (errno == EACCES) { + fprintf(stderr, "ERROR: can not run file\n"); + return -1; + } else if (errno > 0) { + fprintf(stderr, "ERROR: %i errno while attempting to run file\n", errno); + return -1; + } + + return 0; +}