# syntax=docker/dockerfile:1 FROM quay.io/theauthgear/golang:1.26.11-noble AS authgear-once-stage-wrapper WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY ./once/docker_wrapper.go ./ RUN go build -o docker_wrapper -tags 'osusergo netgo static_build timetzdata' . FROM quay.io/theauthgear/authgear-deno:git-243631ad6332 AS authgear-once-stage-authgeardeno FROM authgear-stage-runtime AS authgear-once-stage-final COPY --from=authgear-portal-stage-runtime /usr/local/bin/authgear-portal /usr/local/bin/ ### A note on apt-get install -y --no-install-recommends --no-install-suggests ### ### We want to make sure we do not install anything that is not essential to running ### the packages we install explicitly. ### ### For example, python3 is a suggested package of postgresql-common. ### But we certainly do not need python3 installed in the image. # https://docs.docker.com/reference/dockerfile/#automatic-platform-args-in-the-global-scope ARG TARGETOS ARG TARGETARCH ## Install curl. ## We need it to download minio. RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ curl; \ rm -rf /var/lib/apt/lists/* ## Install less. ## It is useful to view files like postgresql.conf, pg_hba.conf, etc. RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ less; \ rm -rf /var/lib/apt/lists/* ## Install jq. ## We need it to do some JSON manipulation. RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ jq; \ rm -rf /var/lib/apt/lists/* ## Install yq. ## We need it to do some YAML manipulation. RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ yq; \ rm -rf /var/lib/apt/lists/* ## Install sudo ## We do not run the container as root so we need it so that the user can become root as needed. RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ sudo; \ rm -rf /var/lib/apt/lists/* ## Install locales and set LANG ## initdb uses LANG to determine the locale of the database. RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ locales; \ rm -rf /var/lib/apt/lists/*; \ echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ locale-gen; \ locale -a | grep 'en_US.utf8' ENV LANG=en_US.utf8 ## Create the user we use to run the container. ## PostgreSQL does not support running as "root". ## The default user of a PostgreSQL installation is "postgres". ## We do not want to use "postgres" neither. RUN set -eux; \ groupadd --system authgear --gid=900; \ useradd --system --gid=900 --uid=900 --home-dir=/home/authgear --shell=/bin/bash authgear; \ install --verbose --directory --owner authgear --group authgear --mode=1750 /home/authgear ## Allow the user to run sudo, and run it without password. RUN set -eux; \ usermod --append --groups sudo authgear; \ printf "authgear ALL=(ALL) NOPASSWD:ALL\n" > /etc/sudoers.d/900-authgear ## Install PostgreSQL 16.x with pg_partman ## ## ## We have to install the package postgresql-common first. ## The package postgresql-common installs the following file ## ## /etc/postgresql-common/createcluster.conf ## ## In this file, there is an option create_main_cluster. ## We have to uncomment that option, and set it to false, so that ## when the package postgresql-MAJOR is installed, it does not automatically ## run initdb to create a database that we are not going to use. ## ## ## The installed files belong to the user "postgres". ## We change them back to "authgear". ## \! -path '/proc/*' to skip searching in /proc/ as that would result in file not found error. ## ## ## The following files are installed sample configuration files. ## ## /usr/share/postgresql/16/pg_ident.conf.sample ## /usr/share/postgresql/16/pg_service.conf.sample ## /usr/share/postgresql/16/postgresql.conf.sample ## /usr/share/postgresql/16/pg_hba.conf.sample ## ## In particular, we want to patch the following files: ## ## /usr/share/postgresql/16/postgresql.conf.sample ## ## By default, there is a line `#listen_addresses = 'localhost'`. ## We want to uncomment it and change the value to '*', so that ## the Docker host can access it. ## ## /usr/share/postgresql/16/pg_hba.conf.sample ## ## By default, pg_hba.conf does not specify how to authenticate connection NOT from the loopback address. ## We want to add a line to specify it. ## initdb will replace the token `@authmethodhost@` and `@authmethodlocal@` in this file with the given value of ## --auth-host and --auth-local respectively. ## See https://doxygen.postgresql.org/initdb_8c.html ## So the line we add should use the token. ENV PG_MAJOR=16 RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ postgresql-common; \ sed -E -i "s,^#(create_main_cluster)\\s*=\\s*true,\\1 = false," \ /usr/share/postgresql-common/createcluster.conf \ /etc/postgresql-common/createcluster.conf \ ; \ apt-get install -y --no-install-recommends --no-install-suggests \ postgresql-16=16.\* postgresql-16-partman; \ rm -rf /var/lib/apt/lists/*; \ find / \ -user postgres \ \! -path '/proc/*' \ -exec chown authgear:authgear '{}' \; ; \ sed -E -i "s,^#?(listen_addresses)\\s*=\\s*\\S+,\\1 = '*'," "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ printf "host\tall\tall\tall\t%s\n" "@authmethodhost@" >> "/usr/share/postgresql/$PG_MAJOR/pg_hba.conf.sample" ENV PATH=/usr/lib/postgresql/$PG_MAJOR/bin:$PATH ## Install Redis 7.0.x ## ## ## The default configuration of Redis 7.0 can be found here. ## https://raw.githubusercontent.com/redis/redis/7.0/redis.conf ## ## Note that /etc/redis/redis.conf IS NOT the default configuration ## In particular, it has the following changes: ## ## daemonize yes ## pidfile /run/redis/redis-server.pid ## logfile /var/log/redis/redis-server.log ## dir AUTHGEARONCE_REDIS_DATA_DIRECTORY ## ## Use this command to what out which option are not commented. ## ## curl https://raw.githubusercontent.com/redis/redis/7.0/redis.conf | grep -v '^#' | sed -E '/^\s*$/d' > redis.conf ## ## In particular, we need to change the following options. ## ## daemonize no ## We do not run redis-server as daemon. ## ## pidfile /var/run/redis/redis.pid ## Write the pid to a location we know. ## ## logfile "" ## Ask redis-server to write to stdout. ## ## dir AUTHGEARONCE_REDIS_DATA_DIRECTORY ## Make sure when the config file is used, the data directory is predictable. ## ## bind * -::* ## So that the Docker host can access it. ## ## set-proc-title no ## Keep the original process title. ## ## aclfile ## Specify password for the default user. ## ## appendonly yes ## Enable AOF. ## ## auto-aof-rewrite-percentage 50 ## The default is 100%, which means when redis starts with a very large AOF (near the memory limit) ## it will not be able to rewrite the AOF (since it has no memory to do so). RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ redis=5:7.0.\*; \ rm -rf /var/lib/apt/lists/*; \ find / \ -user redis \ \! -path '/proc/*' \ -exec chown authgear:authgear '{}' \; COPY ./once/redis.conf.original /etc/redis/redis.conf.original RUN set -eux; \ expected=$(sha256sum /etc/redis/redis.conf.original | awk '{ print $1 }'); \ actual=$(sha256sum /etc/redis/redis.conf | awk '{ print $1 }'); \ if [ "$expected" != "$actual" ]; then echo 1>&2 echo '/etc/redis/redis.conf has changed. Please review the changes.'; exit 1; fi; COPY ./once/redis.conf /etc/redis/redis.conf ## Install Ngnix RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ nginx; \ rm -rf /var/lib/apt/lists/*; \ ln -sf /dev/stdout /var/log/nginx/access.log; \ ln -sf /dev/stderr /var/log/nginx/error.log COPY --chown=authgear:authgear ./once/nginx/dhparam ./once/nginx/nginx.conf.sample /etc/nginx/ COPY --chown=authgear:authgear ./once/nginx/snippets /etc/nginx/snippets/ ## Install certbot. RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends --no-install-suggests \ certbot \ python3-certbot-nginx; \ rm -rf /var/lib/apt/lists/*; \ cp /etc/letsencrypt/cli.ini /home/authgear/certbot.ini.example; \ chown authgear:authgear /home/authgear/certbot.ini.example ARG MINIO_RELEASE=20250207232109.0.0 ARG MC_RELEASE=20250208191421.0.0 ## Install minio and mcli. RUN set -eux; \ cd /home/authgear; \ curl -q -s https://dl.min.io/server/minio/release/${TARGETOS}-${TARGETARCH}/archive/minio_${MINIO_RELEASE}_${TARGETARCH}.deb -o minio_${MINIO_RELEASE}_${TARGETARCH}.deb; \ curl -q -s https://dl.min.io/server/minio/release/${TARGETOS}-${TARGETARCH}/archive/minio_${MINIO_RELEASE}_${TARGETARCH}.deb.sha256sum -o minio_${MINIO_RELEASE}_${TARGETARCH}.deb.sha256sum; \ curl -q -s https://dl.min.io/client/mc/release/${TARGETOS}-${TARGETARCH}/archive/mcli_${MC_RELEASE}_${TARGETARCH}.deb -o mcli_${MC_RELEASE}_${TARGETARCH}.deb; \ curl -q -s https://dl.min.io/client/mc/release/${TARGETOS}-${TARGETARCH}/archive/mcli_${MC_RELEASE}_${TARGETARCH}.deb.sha256sum -o mcli_${MC_RELEASE}_${TARGETARCH}.deb.sha256sum; \ sha256sum --check minio_${MINIO_RELEASE}_${TARGETARCH}.deb.sha256sum mcli_${MC_RELEASE}_${TARGETARCH}.deb.sha256sum; \ dpkg --install minio_${MINIO_RELEASE}_${TARGETARCH}.deb; \ dpkg --install mcli_${MC_RELEASE}_${TARGETARCH}.deb; \ rm \ minio_${MINIO_RELEASE}_${TARGETARCH}.deb.sha256sum \ mcli_${MC_RELEASE}_${TARGETARCH}.deb.sha256sum \ minio_${MINIO_RELEASE}_${TARGETARCH}.deb \ mcli_${MC_RELEASE}_${TARGETARCH}.deb USER authgear WORKDIR /home/authgear COPY ./once/resources /home/authgear/resources/ COPY ./once/project-resources /home/authgear/project-resources/ COPY --chown=authgear:authgear ./once/docker-entrypoint.sh ./once/docker-certbot.py /usr/local/bin/ COPY --chown=authgear:authgear ./once/bashrc /home/authgear/.bashrc COPY --from=authgear-once-stage-wrapper --chown=authgear:authgear /src/docker_wrapper /usr/local/bin/ COPY --from=authgear-once-stage-authgeardeno --chown=authgear:authgear /usr/local/bin/authgear-deno /usr/local/bin/deno /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] ENV AUTHGEARONCE_ENV_SHELL_SCRIPT=/var/lib/authgearonce/env.sh ENV PGDATA=/var/lib/authgearonce/postgresql/data ENV AUTHGEARONCE_REDIS_DATA_DIRECTORY=/var/lib/authgearonce/redis/data ENV AUTHGEARONCE_MINIO_DATA_DIRECTORY=/var/lib/authgearonce/minio/data ENV AUTHGEARONCE_CERTBOT_DATA_DIRECTORY=/var/lib/authgearonce/certbot/data ENV MINIO_ROOT_USER=authgear VOLUME /var/lib/authgearonce # NOTE(once): Possibly breaking change # These ports are part of the public API between the once image and the once command. # The once command publish SOME of these ports with `-p` in `docker run`. # # There are published ports. # http EXPOSE 80 # https EXPOSE 443 # # These are unpublished ports. # Given that the machine may be directly connected to the internet, # it is more secure not to publish the port on the host machine at all. # postgres EXPOSE 5432 # redis EXPOSE 6379 # minio EXPOSE 9000 # minio web console EXPOSE 9001 # authgear-deno EXPOSE 8090 # main EXPOSE 3000 # main internal EXPOSE 13000 # resolver EXPOSE 3001 # resolver internal EXPOSE 13001 # admin EXPOSE 3002 # admin internal EXPOSE 13002 # portal EXPOSE 3003 # portal internal EXPOSE 13003 CMD ["docker_wrapper"]