diff --git a/docker/production/.gitlab-ci.yml b/docker/production/.gitlab-ci.yml index 6bea091d..91c434e5 100644 --- a/docker/production/.gitlab-ci.yml +++ b/docker/production/.gitlab-ci.yml @@ -19,7 +19,6 @@ docker-build-rolling: - docker buildx create --use tls-environment - docker buildx build --push --platform=linux/amd64 --file=docker/production/web-server/Dockerfile --tag=${DOCKER_IMAGE_WEB_SERVER}:${TAG} . - docker buildx build --push --platform=linux/amd64 --file=docker/production/app/Dockerfile --tag=${DOCKER_IMAGE_APP}:${TAG} . - - docker buildx build --push --platform=linux/amd64 --file=docker/production/video-clipper/Dockerfile --tag=${DOCKER_IMAGE_VIDEO_CLIPPER}:${TAG} . - docker buildx build --push --platform=linux/amd64 --file=docker/production/castopod/Dockerfile --tag=${DOCKER_IMAGE_CASTOPOD}:${TAG} . needs: - pipeline: $PARENT_PIPELINE_ID @@ -46,7 +45,6 @@ docker-build-main-release: - docker buildx create --use tls-environment - docker buildx build --push --platform=linux/amd64 --file=docker/production/web-server/Dockerfile --tag=${DOCKER_IMAGE_WEB_SERVER}:${CP_VERSION} --tag=${DOCKER_IMAGE_WEB_SERVER}:latest . - docker buildx build --push --platform=linux/amd64 --file=docker/production/app/Dockerfile --tag=${DOCKER_IMAGE_APP}:${CP_VERSION} --tag=${DOCKER_IMAGE_APP}:latest . - - docker buildx build --push --platform=linux/amd64 --file=docker/production/video-clipper/Dockerfile --tag=${DOCKER_IMAGE_VIDEO_CLIPPER}:${CP_VERSION} --tag=${DOCKER_IMAGE_VIDEO_CLIPPER}:latest . # when --platform=linux/amd64,linux/arm64: amd64 image takes too long to be pushed as it needs to wait for arm64 to be built # --> build and push amd64 image to be pushed first, then overwrite manifest after building arm64 - docker buildx build --push --platform=linux/amd64 --file=docker/production/castopod/Dockerfile --tag=${DOCKER_IMAGE_CASTOPOD}:${CP_VERSION} --tag=${DOCKER_IMAGE_CASTOPOD}:latest . @@ -77,7 +75,6 @@ docker-build-alpha-beta-release: - docker buildx create --use tls-environment - docker buildx build --push --platform=linux/amd64 --file=docker/production/web-server/Dockerfile --tag=${DOCKER_IMAGE_WEB_SERVER}:${CP_VERSION} --tag=${DOCKER_IMAGE_WEB_SERVER}:${TAG} . - docker buildx build --push --platform=linux/amd64 --file=docker/production/app/Dockerfile --tag=${DOCKER_IMAGE_APP}:${CP_VERSION} --tag=${DOCKER_IMAGE_APP}:${TAG} . - - docker buildx build --push --platform=linux/amd64 --file=docker/production/video-clipper/Dockerfile --tag=${DOCKER_IMAGE_VIDEO_CLIPPER}:${CP_VERSION} --tag=${DOCKER_IMAGE_VIDEO_CLIPPER}:${TAG} . # when --platform=linux/amd64,linux/arm64: amd64 image takes too long to be pushed as it needs to wait for arm64 to be built # --> build and push amd64 image to be pushed first, then overwrite manifest after building arm64 - docker buildx build --push --platform=linux/amd64 --file=docker/production/castopod/Dockerfile --tag=${DOCKER_IMAGE_CASTOPOD}:${CP_VERSION} --tag=${DOCKER_IMAGE_CASTOPOD}:${TAG} . diff --git a/docker/production/app/Dockerfile b/docker/production/app/Dockerfile index 92231fb4..76c95c93 100644 --- a/docker/production/app/Dockerfile +++ b/docker/production/app/Dockerfile @@ -1,32 +1,44 @@ -FROM docker.io/php:8.1-fpm-alpine3.17 +FROM docker.io/golang:1.20-bookworm AS CRON_BUILDER + +ARG SUPERCRONIC_VERSION=v0.2.25 + +RUN apt-get update && \ + apt-get install -y git && \ + git clone https://github.com/aptible/supercronic.git && \ + cd supercronic && \ + git checkout $SUPERCRONIC_VERSION && \ + go build && \ + mv supercronic /usr/local/bin + + +FROM docker.io/php:8.1-fpm + +COPY --from=CRON_BUILDER /usr/local/bin/supercronic /usr/local/bin/supercronic COPY docker/production/common/prepare_environment.sh /prepare_environment.sh COPY docker/production/app/entrypoint.sh /entrypoint.sh COPY docker/production/app/uploads.template.ini /uploads.template.ini +COPY docker/production/common/crontab.txt /crontab.txt +COPY docker/production/app/supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY castopod /var/www/castopod -RUN echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-activities" > /crontab.txt && \ - echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-websub-publish" >> /crontab.txt -# TODO: remove freetype (package and gd support) and ffmpeg -RUN apk add --no-cache libpng icu-libs freetype libwebp libjpeg-turbo libxpm ffmpeg coreutils gettext && \ - apk add --no-cache --virtual .php-ext-build-dep freetype-dev libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libxpm-dev icu-dev && \ +RUN apt-get update && \ + apt-get install -y supervisor ffmpeg curl gettext-base libfreetype6-dev libjpeg62-turbo-dev libpng-dev libwebp-dev libxpm-dev libpcre2-8-0 libicu-dev && \ + rm -rf /var/lib/apt/lists/* && \ + pecl install -o -f redis && \ + rm -rf /tmp/pear && \ docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm && \ - docker-php-ext-install gd intl mysqli exif && \ - docker-php-ext-enable mysqli gd intl exif && \ - apk del .php-ext-build-dep - -COPY castopod /opt/castopod - -RUN chmod 544 /entrypoint.sh && \ - chmod 444 /crontab.txt && \ - /usr/bin/crontab /crontab.txt - -WORKDIR /opt/castopod - -VOLUME /opt/castopod/public/media + docker-php-ext-install mysqli gd intl exif && \ + docker-php-ext-enable mysqli gd intl exif redis && \ + chmod +x /entrypoint.sh && \ + chmod -R 750 /var/www/castopod && \ + chown -R root:www-data /var/www/castopod && \ + chown -R www-data:www-data /var/www/castopod/writable /var/www/castopod/public/media +WORKDIR /var/www/castopod +VOLUME /var/www/castopod/public/media EXPOSE 9000 ENTRYPOINT [ "sh", "-c" ] - CMD [ "/entrypoint.sh" ] diff --git a/docker/production/app/entrypoint.sh b/docker/production/app/entrypoint.sh index 7e81d438..00ed746f 100644 --- a/docker/production/app/entrypoint.sh +++ b/docker/production/app/entrypoint.sh @@ -1,9 +1,13 @@ #!/bin/sh -ENV_FILE_LOCATION=/opt/castopod/.env +ENV_FILE_LOCATION=/var/www/castopod/.env + +# Fix ownership and permissions of castopod folders +chmod -R 750 /var/www/castopod +chown -R root:www-data /var/www/castopod +chown -R www-data:www-data /var/www/castopod/writable /var/www/castopod/public/media . /prepare_environment.sh cat /uploads.template.ini | envsubst '$CP_MAX_BODY_SIZE$CP_MAX_BODY_SIZE_BYTES$CP_TIMEOUT$CP_PHP_MEMORY_LIMIT' > /usr/local/etc/php/conf.d/uploads.ini -/usr/sbin/crond -f /crontab.txt -L /dev/stdout & -/usr/local/sbin/php-fpm +supervisord diff --git a/docker/production/app/supervisord.conf b/docker/production/app/supervisord.conf new file mode 100644 index 00000000..20148886 --- /dev/null +++ b/docker/production/app/supervisord.conf @@ -0,0 +1,20 @@ +[supervisord] +nodaemon=true + +[program:supercronic] +command=supercronic /crontab.txt +autostart=true +autorestart=unexpected +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:fpm] +command=/usr/local/sbin/php-fpm +autostart=true +autorestart=unexpected +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker/production/castopod/Dockerfile b/docker/production/castopod/Dockerfile index fc5db997..3346ce6d 100644 --- a/docker/production/castopod/Dockerfile +++ b/docker/production/castopod/Dockerfile @@ -1,6 +1,6 @@ -FROM docker.io/golang:1.20-bullseye AS CRON_BUILDER +FROM docker.io/golang:1.20-bookworm AS CRON_BUILDER -ARG SUPERCRONIC_VERSION=v0.2.1 +ARG SUPERCRONIC_VERSION=v0.2.25 RUN apt-get update && \ apt-get install -y git && \ @@ -37,7 +37,7 @@ COPY docker/production/common/prepare_environment.sh /prepare_environment.sh COPY docker/production/castopod/entrypoint.sh /entrypoint.sh COPY castopod /var/www/castopod COPY docker/production/castopod/config.template.json /config.template.json -COPY docker/production/castopod/crontab.txt /crontab.txt +COPY docker/production/common/crontab.txt /crontab.txt COPY docker/production/castopod/supervisord.conf /etc/supervisor/conf.d/supervisord.conf RUN apt-get update && \ diff --git a/docker/production/castopod/crontab.txt b/docker/production/common/crontab.txt similarity index 100% rename from docker/production/castopod/crontab.txt rename to docker/production/common/crontab.txt diff --git a/docker/production/video-clipper/Dockerfile b/docker/production/video-clipper/Dockerfile deleted file mode 100644 index 8f91f97b..00000000 --- a/docker/production/video-clipper/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -FROM docker.io/php:8.1-bullseye - -ENV SUPERCRONIC_VERSION=v0.2.1 - -COPY docker/production/video-clipper/entrypoint.sh /entrypoint.sh - -RUN echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-video-clips" >> /crontab.txt - -RUN apt update && \ - apt install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libwebp-dev libxpm-dev libicu-dev && \ - docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm && \ - docker-php-ext-install mysqli gd intl && \ - docker-php-ext-enable mysqli gd intl - -RUN apt update && \ - apt install -y ffmpeg curl && \ - curl -OL https://github.com/aptible/supercronic/releases/download/$SUPERCRONIC_VERSION/supercronic-linux-amd64 && \ - mv supercronic-linux-amd64 /usr/local/bin/supercronic && \ - chmod +x /usr/local/bin/supercronic - -COPY castopod /opt/castopod - -RUN chmod 544 /entrypoint.sh && \ - chmod 444 /crontab.txt - -WORKDIR /opt/castopod - -VOLUME /opt/castopod/public/media - -ENTRYPOINT [ "sh", "-c" ] - -CMD [ "/entrypoint.sh" ] diff --git a/docker/production/video-clipper/entrypoint.sh b/docker/production/video-clipper/entrypoint.sh deleted file mode 100644 index 638e3dfc..00000000 --- a/docker/production/video-clipper/entrypoint.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh - -if [ -z "${CP_DATABASE_HOSTNAME}" ] -then - echo "CP_DATABASE_HOSTNAME is empty, using default" - CP_DATABASE_HOSTNAME="mariadb" -fi - -if [ -z "${CP_DATABASE_PREFIX}" ] -then - echo "CP_DATABASE_PREFIX is empty, using default" - CP_DATABASE_PREFIX="cp_" -fi - -if [ -z "${CP_DATABASE_NAME}" ] -then - if [ -z "${MYSQL_DATABASE}" ] - then - echo "When CP_DATABASE_NAME is empty, MYSQL_DATABASE must be set" - exit 1 - fi - - echo "CP_DATABASE_NAME is empty, using mysql variable" - CP_DATABASE_NAME="${MYSQL_DATABASE}" -fi - -if [ -z "${CP_DATABASE_USERNAME}" ] -then - if [ -z "${MYSQL_USER}" ] - then - echo "When CP_DATABASE_USERNAME is empty, MYSQL_USER must be set" - exit 1 - fi - - echo "CP_DATABASE_USERNAME is empty, using mysql variable" - CP_DATABASE_USERNAME="${MYSQL_USER}" -fi - -if [ -z "${CP_DATABASE_PASSWORD}" ] -then - if [ -z "${MYSQL_PASSWORD}" ] - then - echo "When CP_DATABASE_PASSWORD is empty, MYSQL_PASSWORD must be set" - exit 1 - fi - - echo "CP_DATABASE_PASSWORD is empty, using mysql variable" - CP_DATABASE_PASSWORD="${MYSQL_PASSWORD}" -fi - -cat << EOF >> /opt/castopod/.env -database.default.hostname="${CP_DATABASE_HOSTNAME}" -database.default.database="${CP_DATABASE_NAME}" -database.default.username="${CP_DATABASE_USERNAME}" -database.default.password="${CP_DATABASE_PASSWORD}" -database.default.DBPrefix="${CP_DATABASE_PREFIX}" -EOF - -echo "Using config:" -cat /opt/castopod/.env - -supercronic /crontab.txt diff --git a/docker/production/web-server/Dockerfile b/docker/production/web-server/Dockerfile index 5d735499..c3ce4328 100644 --- a/docker/production/web-server/Dockerfile +++ b/docker/production/web-server/Dockerfile @@ -1,20 +1,18 @@ -FROM docker.io/nginx:1.21-alpine - -VOLUME /var/www/html/media - -EXPOSE 80 - -WORKDIR /var/www/html +FROM docker.io/nginx:1.25 COPY docker/production/web-server/entrypoint.sh /entrypoint.sh - -RUN chmod +x /entrypoint.sh && \ - apk add --no-cache curl gettext - -HEALTHCHECK --interval=30s --timeout=3s CMD curl --fail http://localhost || exit 1 - COPY docker/production/web-server/nginx.template.conf /nginx.template.conf - COPY castopod/public /var/www/html +RUN chmod +x /entrypoint.sh && \ + apt-get update && \ + apt-get install -y curl gettext-base && \ + rm -rf /var/lib/apt/lists/* && \ + usermod -aG www-data nginx + +HEALTHCHECK --interval=30s --timeout=3s CMD curl --fail http://localhost || exit 1 +VOLUME /var/www/html/media +EXPOSE 80 +WORKDIR /var/www/html + CMD ["/entrypoint.sh"] diff --git a/docker/production/web-server/nginx.template.conf b/docker/production/web-server/nginx.template.conf index 56bed67d..bb7b91ec 100644 --- a/docker/production/web-server/nginx.template.conf +++ b/docker/production/web-server/nginx.template.conf @@ -64,7 +64,7 @@ http { fastcgi_index index.php; fastcgi_param SERVER_NAME $host; fastcgi_pass php-handler; - fastcgi_param SCRIPT_FILENAME /opt/castopod/public/$fastcgi_script_name; + fastcgi_param SCRIPT_FILENAME /var/www/castopod/public/$fastcgi_script_name; try_files $uri =404; fastcgi_read_timeout 3600; fastcgi_send_timeout 3600; diff --git a/docs/src/getting-started/docker.md b/docs/src/getting-started/docker.md index 437ca7ad..0b6a1abf 100644 --- a/docs/src/getting-started/docker.md +++ b/docs/src/getting-started/docker.md @@ -39,7 +39,7 @@ can be added as a cache handler. services: app: - image: castopod/app:latest + image: castopod/castopod:latest container_name: "castopod-app" volumes: - castopod-media:/var/www/castopod/public/media