build(docker): add production-ready DockerFiles

- add docker images for app (castopod) and web-server (nginx)
- ci: deploy images continuously to a docker hub using kaniko
- ci: trigger docker-build-rolling on develop branch
- move development DockerFile to docker directory

closes #200
This commit is contained in:
Romain de Laage 2022-06-26 12:03:22 +00:00 committed by Yassine Doghri
parent de8b1df948
commit 0c0730be69
10 changed files with 335 additions and 1 deletions

View File

@ -5,6 +5,7 @@ stages:
- quality
- bundle
- release
- build
- deploy
php-dependencies:
@ -151,3 +152,16 @@ documentation:
only:
changes:
- docs/**/*
docker:
stage: build
trigger:
include: docker/production/.gitlab-ci.yml
strategy: depend
variables:
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
only:
refs:
- develop
variables:
- $CI_PROJECT_NAMESPACE == "adaures"

View File

@ -7,7 +7,7 @@ services:
app:
build:
context: .
dockerfile: Dockerfile
dockerfile: docker/development/Dockerfile
container_name: app
command: /bin/sh -c "crontab ./crontab && cron && service cron reload && php spark serve - 0.0.0.0"
ports:

View File

@ -0,0 +1,20 @@
stages:
- build
docker-build-rolling:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
variables:
TAG: $CI_COMMIT_BRANCH
script:
- cp ${DOCKER_HUB_CONFIG} /kaniko/.docker/config.json
- /kaniko/executor --context . --dockerfile docker/production/web-server/Dockerfile --destination ${DOCKER_IMAGE_WEB_SERVER}:${TAG}
- /kaniko/executor --context . --dockerfile docker/production/app/Dockerfile --destination ${DOCKER_IMAGE_APP}:${TAG}
needs:
- pipeline: $PARENT_PIPELINE_ID
job: bundle
only:
refs:
- develop

View File

@ -0,0 +1,40 @@
FROM docker.io/alpine:3.13 AS ffmpeg-downloader
RUN apk add --no-cache curl && \
curl https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz -o ffmpeg.tar.xz && \
tar -xJf ffmpeg.tar.xz && \
mv ffmpeg-5.0.1-amd64-static ffmpeg
FROM docker.io/php:8.0-fpm-alpine3.13
COPY docker/production/app/entrypoint.sh /entrypoint.sh
COPY docker/production/app/uploads.ini /usr/local/etc/php/conf.d/uploads.ini
RUN echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-activities" > /crontab.txt && \
echo "* * * * 10 /usr/local/bin/php /opt/castopod/public/index.php scheduled-video-clips" >> /crontab.txt && \
echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-websub-publish" >> /crontab.txt
RUN apk add --no-cache libpng icu-libs freetype libwebp libjpeg-turbo libxpm ffmpeg && \
apk add --no-cache --virtual .php-ext-build-dep freetype-dev libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libxpm-dev icu-dev && \
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
COPY --from=ffmpeg-downloader /ffmpeg/ffmpeg /ffmpeg/ffprobe /ffmpeg/qt-faststart /usr/local/bin/
RUN chmod 544 /entrypoint.sh && \
chmod 444 /crontab.txt && \
/usr/bin/crontab /crontab.txt
WORKDIR /opt/castopod
VOLUME /opt/castopod/public/media
EXPOSE 9000
ENTRYPOINT [ "sh", "-c" ]
CMD [ "/entrypoint.sh" ]

View File

@ -0,0 +1,150 @@
#!/bin/sh
if [ -z "${CP_BASEURL}" ]
then
echo "CP_BASEURL must be set"
exit 1
fi
if [ -z "${CP_MEDIA_BASEURL}" ]
then
echo "CP_MEDIA_BASEURL is empty, leaving empty by default"
fi
if [ -z "${CP_ADMIN_GATEWAY}" ]
then
echo "CP_ADMIN_GATEWAY is empty, using default"
CP_ADMIN_GATEWAY="cp-admin"
fi
if [ -z "${CP_AUTH_GATEWAY}" ]
then
echo "CP_AUTH_GATEWAY is empty, using default"
CP_AUTH_GATEWAY="cp-auth"
fi
if [ -z "${CP_ANALYTICS_SALT}" ]
then
echo "CP_ANALYTICS_SALT is empty, this is mandatory, generate a new one with tr -dc \\!\\#-\\&\\(-\\[\\]-\\_a-\\~ </dev/urandom | head -c 64"
exit 1
fi
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
if [ ! -z "${CP_REDIS_HOST}" ]
then
echo "Using redis cache handler"
CP_CACHE_HANDLER="redis"
if [ -z "${CP_REDIS_PASSWORD}" ]
then
echo "CP_REDIS_PASSWORD is empty, using default"
CP_REDIS_PASSWORD="null"
else
CP_REDIS_PASSWORD="\"${CP_REDIS_PASSWORD}\""
fi
if [ -z "${CP_REDIS_PORT}" ]
then
echo "CP_REDIS_PORT is empty, using default"
CP_REDIS_PORT="6379"
fi
if [ -z "${CP_REDIS_DATABASE}" ]
then
echo "CP_REDIS_DATABASE is empty, using default"
CP_REDIS_DATABASE="0"
fi
else
echo "Using file cache handler"
CP_CACHE_HANDLER="file"
fi
cat << EOF > /opt/castopod/.env
app.baseURL="${CP_BASEURL}"
app.mediaBaseURL="${CP_MEDIA_BASEURL}"
EOF
if [ "${CP_DISABLE_HTTPS}" == "1" ]
then
echo "HTTPS redirection is disabled for test purpose, please enable it in production mode"
echo "app.forceGlobalSecureRequests=false" >> /opt/castopod/.env
else
echo "HTTPS redirection is enabled by default (mandatory to federate with the fediverse), use CP_DISABLE_HTTPS=1 to disable it for test purpose"
fi
cat << EOF >> /opt/castopod/.env
admin.gateway="${CP_ADMIN_GATEWAY}"
auth.gateway="${CP_AUTH_GATEWAY}"
analytics.salt="${CP_ANALYTICS_SALT}"
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}"
cache.handler="${CP_CACHE_HANDLER}"
EOF
if [ "${CP_CACHE_HANDLER}" == "redis" ]
then
cat << EOF >> /opt/castopod/.env
cache.redis.host="${CP_REDIS_HOST}"
cache.redis.password=${CP_REDIS_PASSWORD}
cache.redis.port=${CP_REDIS_PORT}
cache.redis.database=${CP_REDIS_DATABASE}
EOF
fi
echo "Using config:"
cat /opt/castopod/.env
/usr/sbin/crond -f /crontab.txt -L /dev/stdout &
/usr/local/sbin/php-fpm

View File

@ -0,0 +1,5 @@
file_uploads = On
memory_limit = 512M
upload_max_filesize = 500M
post_max_size = 512M
max_execution_time = 300

View File

@ -0,0 +1,20 @@
FROM docker.io/nginx:1.21-alpine
VOLUME /var/www/html/media
EXPOSE 80
WORKDIR /var/www/html
COPY docker/production/web-server/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh && \
apk add --no-cache curl
HEALTHCHECK --interval=30s --timeout=3s CMD curl --fail http://localhost || exit 1
COPY docker/production/web-server/nginx.conf /etc/nginx/nginx.conf
COPY castopod/public /var/www/html
CMD ["/entrypoint.sh"]

View File

@ -0,0 +1,9 @@
#!/bin/sh
if [ -z "${CP_HOST_BACK}" ]
then
echo "CP_HOST_BACK is empty, using default"
CP_HOST_BACK="back"
fi
sed -i "s/CP_HOST_BACK/${CP_HOST_BACK}/" /etc/nginx/nginx.conf
nginx -g "daemon off;"

View File

@ -0,0 +1,76 @@
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Real-IP;
upstream php-handler {
server CP_HOST_BACK:9000;
}
server {
listen 80;
root /var/www/html;
index index.php index.html index.htm;
client_max_body_size 1G;
fastcgi_buffers 64 4K;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_types application/atom+xml application/javascript audio/mpeg application/rss+xml image/bmp image/png image/jpeg image/webp image/svg+xml image/x-icon video/mp4 text/css text/plain text/html;
location ~ /.*\.(png|ico|txt|js|js\.map)$ {
try_files $uri =404;
}
location ~ /(assets|media)/.*$ {
try_files $uri =404;
}
location /.well-known/GDPR.yml {
try_files $uri =404;
}
location / {
fastcgi_param SCRIPT_FILENAME /opt/castopod/public/index.php;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_pass php-handler;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_param SCRIPT_FILENAME /opt/castopod/public/$fastcgi_script_name;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_pass php-handler;
}
}
}