From 1f61df9cf008f4f7bd3f1c5a9f4ea415174dcd66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 27 Jun 2019 12:03:08 +0200 Subject: [PATCH] Upgrade Dockerfile --- .dockerignore | 22 ++- .travis.yml | 6 +- Dockerfile | 168 ++++++++++++++--------- README.md | 10 +- docker-compose.yaml | 10 +- docker/nginx/conf.d/default.conf | 4 +- docker/{app => php}/conf.d/symfony.ini | 0 docker/{app => php}/docker-entrypoint.sh | 18 +-- 8 files changed, 143 insertions(+), 95 deletions(-) rename docker/{app => php}/conf.d/symfony.ini (100%) rename docker/{app => php}/docker-entrypoint.sh (63%) diff --git a/.dockerignore b/.dockerignore index 3f43985..af4ff76 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,23 @@ **/*.log +**/*.md +**/*.php~ **/._* +**/.dockerignore **/.DS_Store -**/.gitignore +**/.git/ **/.gitattributes +**/.gitignore +**/.gitmodules +**/Dockerfile **/Thumbs.db -.dockerignore -Dockerfile -docker-compose.yaml +.editorconfig +.env* +!.env.local.php +.php_cs.cache +bin/* +!bin/console +docker/db/data/ +helm/ +public/bundles/ +var/ +vendor/ diff --git a/.travis.yml b/.travis.yml index 2a5d19a..875ea2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,9 +26,9 @@ script: - docker-compose build --pull - docker-compose up -d - sleep 30 - - docker-compose exec -T app composer req sensiolabs/security-checker - - docker-compose exec -T app bin/console security:check - - docker-compose run --no-deps -T app composer validate --no-check-publish + - docker-compose exec -T php composer req sensiolabs/security-checker + - docker-compose exec -T php bin/console security:check + - docker-compose run --no-deps -T php composer validate --no-check-publish - curl http://localhost # Client - curl -k https://localhost # Client (HTTP/2) - docker-compose logs # Display logs if anything wrong diff --git a/Dockerfile b/Dockerfile index 2db8134..164bf01 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,80 +1,75 @@ # the different stages of this Dockerfile are meant to be built into separate images +# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage # https://docs.docker.com/compose/compose-file/#target -ARG PHP_VERSION=7.2 + +# https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact +ARG PHP_VERSION=7.3 ARG NGINX_VERSION=1.15 -### NGINX -FROM nginx:${NGINX_VERSION}-alpine AS symfony_docker_nginx -COPY docker/nginx/conf.d /etc/nginx/conf.d/ -COPY public /srv/app/public/ - -### H2 PROXY -FROM alpine:latest AS symfony_docker_h2-proxy-cert - -RUN apk add --no-cache openssl - -# Use this self-generated certificate only in dev, IT IS NOT SECURE! -RUN openssl genrsa -des3 -passout pass:NotSecure -out server.pass.key 2048 -RUN openssl rsa -passin pass:NotSecure -in server.pass.key -out server.key -RUN rm server.pass.key -RUN openssl req -new -passout pass:NotSecure -key server.key -out server.csr \ - -subj '/C=SS/ST=SS/L=Gotham City/O=Symfony/CN=localhost' -RUN openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt - -FROM nginx:${NGINX_VERSION}-alpine AS symfony_docker_h2-proxy - -RUN mkdir -p /etc/nginx/ssl/ -COPY --from=symfony_docker_h2-proxy-cert server.key server.crt /etc/nginx/ssl/ -COPY ./docker/h2-proxy/default.conf /etc/nginx/conf.d/default.conf - -### PHP +# "php" stage FROM php:${PHP_VERSION}-fpm-alpine AS symfony_docker_php +# persistent / runtime deps RUN apk add --no-cache \ - git \ - icu-libs \ - zlib \ - jq + acl \ + file \ + gettext \ + git \ + jq \ + ; -ENV APCU_VERSION 5.1.12 -RUN set -eux \ - && apk add --no-cache --virtual .build-deps \ - $PHPIZE_DEPS \ - icu-dev \ - zlib-dev \ - && docker-php-ext-install -j$(nproc) \ - intl \ - zip \ - && pecl install \ - apcu-${APCU_VERSION} \ - && docker-php-ext-enable --ini-name 20-apcu.ini apcu \ - && docker-php-ext-enable --ini-name 05-opcache.ini opcache \ - && runDeps="$( \ - scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \ - | tr ',' '\n' \ - | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ - )" \ - && apk add --no-cache --virtual .api-phpexts-rundeps $runDeps \ - && apk del .build-deps +ARG APCU_VERSION=5.1.17 +RUN set -eux; \ + apk add --no-cache --virtual .build-deps \ + $PHPIZE_DEPS \ + icu-dev \ + libzip-dev \ + postgresql-dev \ + zlib-dev \ + ; \ + \ + docker-php-ext-configure zip --with-libzip; \ + docker-php-ext-install -j$(nproc) \ + intl \ + zip \ + ; \ + pecl install \ + apcu-${APCU_VERSION} \ + ; \ + pecl clear-cache; \ + docker-php-ext-enable \ + apcu \ + opcache \ + ; \ + \ + runDeps="$( \ + scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \ + | tr ',' '\n' \ + | sort -u \ + | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-cache --virtual .phpexts-rundeps $runDeps; \ + \ + apk del .build-deps -RUN ln -s $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini -COPY docker/app/conf.d/symfony.ini $PHP_INI_DIR/conf.d/symfony.ini COPY --from=composer:latest /usr/bin/composer /usr/bin/composer -COPY docker/app/docker-entrypoint.sh /usr/local/bin/docker-app-entrypoint -RUN chmod +x /usr/local/bin/docker-app-entrypoint - -WORKDIR /srv/app -ENTRYPOINT ["docker-app-entrypoint"] -CMD ["php-fpm"] +RUN ln -s $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini +COPY docker/php/conf.d/symfony.ini $PHP_INI_DIR/conf.d/symfony.ini # https://getcomposer.org/doc/03-cli.md#composer-allow-superuser -ENV COMPOSER_ALLOW_SUPERUSER 1 +ENV COMPOSER_ALLOW_SUPERUSER=1 +# install Symfony Flex globally to speed up download of Composer packages (parallelized prefetching) +RUN set -eux; \ + composer global require "symfony/flex" --prefer-dist --no-progress --no-suggest --classmap-authoritative; \ + composer clear-cache +ENV PATH="${PATH}:/root/.composer/vendor/bin" -# Use prestissimo to speed up builds -RUN composer global require "symfony/flex" --prefer-dist --no-progress --no-suggest --classmap-authoritative --no-interaction +WORKDIR /srv/app + +# build for production +ARG APP_ENV=prod # Allow to use development versions of Symfony ARG STABILITY="stable" @@ -84,14 +79,53 @@ ENV STABILITY ${STABILITY:-stable} ARG SYMFONY_VERSION="" # Download the Symfony skeleton and leverage Docker cache layers -RUN composer create-project "symfony/skeleton ${SYMFONY_VERSION}" . --stability=$STABILITY --prefer-dist --no-dev --no-progress --no-scripts --no-plugins --no-interaction +RUN composer create-project "symfony/skeleton ${SYMFONY_VERSION}" . --stability=$STABILITY --prefer-dist --no-dev --no-progress --no-scripts --no-plugins --no-interaction; \ + composer clear-cache ###> recipes ### ###< recipes ### COPY . . -RUN mkdir -p var/cache var/logs var/sessions \ - && composer install --prefer-dist --no-dev --no-scripts --no-progress --no-suggest --classmap-authoritative --no-interaction \ - && composer clear-cache \ - && chown -R www-data var +RUN set -eux; \ + mkdir -p var/cache var/log; \ + composer dump-autoload --classmap-authoritative --no-dev; \ + composer run-script --no-dev post-install-cmd; sync +VOLUME /srv/app/var + +COPY docker/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint +RUN chmod +x /usr/local/bin/docker-entrypoint + +ENTRYPOINT ["docker-entrypoint"] +CMD ["php-fpm"] + + +# "nginx" stage +# depends on the "php" stage above +FROM nginx:${NGINX_VERSION}-alpine AS symfony_docker_nginx + +COPY docker/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf + +WORKDIR /srv/app + +COPY --from=symfony_docker_php /srv/app/public public/ + +# "h2-proxy-cert" stage +FROM alpine:latest AS symfony_docker_h2-proxy-cert + +RUN apk add --no-cache openssl + +# Use this self-generated certificate only in dev, IT IS NOT SECURE! +RUN openssl genrsa -des3 -passout pass:NotSecure -out server.pass.key 2048 +RUN openssl rsa -passin pass:NotSecure -in server.pass.key -out server.key +RUN rm server.pass.key +RUN openssl req -new -passout pass:NotSecure -key server.key -out server.csr \ + -subj '/C=SS/ST=SS/L=Gotham City/O=Symfony/CN=localhost' +RUN openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt + +### "h2-proxy" stage +FROM nginx:${NGINX_VERSION}-alpine AS symfony_docker_h2-proxy + +RUN mkdir -p /etc/nginx/ssl/ +COPY --from=symfony_docker_h2-proxy-cert server.key server.crt /etc/nginx/ssl/ +COPY ./docker/h2-proxy/default.conf /etc/nginx/conf.d/default.conf diff --git a/README.md b/README.md index c6e6393..ac8bb3e 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ configuration remains untouched. As example, an override could look like this: ```yaml -version: '3.4' +version: "3.4" services: app: @@ -78,9 +78,9 @@ services: Then run: -````bash +```bash docker-compose up -d -```` +``` If `docker-compose.yaml` and a `docker-compose.override.yaml` are present on the same directory level, Docker Compose combines the two files into a single configuration, applying the configuration in the `docker-compose.override.yaml` file over and in addition to the values in the `docker-compose.yaml` file. @@ -89,7 +89,7 @@ If `docker-compose.yaml` and a `docker-compose.override.yaml` are present on the Inspect the installation with the following command. The requested Xdebug version should be displayed in the output. ```bash -$ docker-compose exec app php --version +$ docker-compose exec php php --version PHP 7.2.8 (cli) (built: Jul 21 2018 08:09:37) ( NTS ) Copyright (c) 1997-2018 The PHP Group @@ -100,7 +100,7 @@ Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies ### Editing Permissions on Linux -If you work on linux and cannot edit some of the project files right after the first installation, you can run `docker-compose run --rm app chown -R $(id -u):$(id -g) .` to set yourself as owner of the project files that were created by the docker container. +If you work on linux and cannot edit some of the project files right after the first installation, you can run `docker-compose run --rm php chown -R $(id -u):$(id -g) .` to set yourself as owner of the project files that were created by the docker container. ## Credits diff --git a/docker-compose.yaml b/docker-compose.yaml index 36bdd30..757b48a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,7 +1,7 @@ -version: '3.4' +version: "3.4" services: - app: + php: build: context: . target: symfony_docker_php @@ -24,13 +24,13 @@ services: context: . target: symfony_docker_nginx depends_on: - - app + - php volumes: # Comment out the next line in production - ./docker/nginx/conf.d:/etc/nginx/conf.d:ro - ./public:/srv/app/public:ro ports: - - '80:80' + - "80:80" # This HTTP/2 proxy is not secure: it should only be used in dev h2-proxy: @@ -42,4 +42,4 @@ services: volumes: - ./docker/h2-proxy/default.conf:/etc/nginx/conf.d/default.conf:ro ports: - - '443:443' + - "443:443" diff --git a/docker/nginx/conf.d/default.conf b/docker/nginx/conf.d/default.conf index 9efd420..8474564 100644 --- a/docker/nginx/conf.d/default.conf +++ b/docker/nginx/conf.d/default.conf @@ -7,10 +7,10 @@ server { } location ~ ^/index\.php(/|$) { #resolver 127.0.0.11; - #set $upstream_host app; + #set $upstream_host php; #fastcgi_pass $upstream_host:9000; # Uncomment the previous lines and comment the next one to enable dynamic resolution (incompatible with Kubernetes) - fastcgi_pass app:9000; + fastcgi_pass php:9000; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; # When you are using symlinks to link the document root to the diff --git a/docker/app/conf.d/symfony.ini b/docker/php/conf.d/symfony.ini similarity index 100% rename from docker/app/conf.d/symfony.ini rename to docker/php/conf.d/symfony.ini diff --git a/docker/app/docker-entrypoint.sh b/docker/php/docker-entrypoint.sh similarity index 63% rename from docker/app/docker-entrypoint.sh rename to docker/php/docker-entrypoint.sh index fa8bbea..56ee861 100755 --- a/docker/app/docker-entrypoint.sh +++ b/docker/php/docker-entrypoint.sh @@ -6,12 +6,12 @@ if [ "${1#-}" != "$1" ]; then set -- php-fpm "$@" fi -if [ "$1" = 'php-fpm' ] || [ "$1" = 'bin/console' ]; then - PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-production" - if [ "$APP_ENV" != 'prod' ]; then - PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-development" - fi - ln -sf "$PHP_INI_RECOMMENDED" "$PHP_INI_DIR/php.ini" +if [ "$1" = 'php-fpm' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then + PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-production" + if [ "$APP_ENV" != 'prod' ]; then + PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-development" + fi + ln -sf "$PHP_INI_RECOMMENDED" "$PHP_INI_DIR/php.ini" # The first time volumes are mounted, the project needs to be recreated if [ ! -f composer.json ]; then @@ -23,12 +23,12 @@ if [ "$1" = 'php-fpm' ] || [ "$1" = 'bin/console' ]; then cp -Rp tmp/. . rm -Rf tmp/ elif [ "$APP_ENV" != 'prod' ]; then - # Always try to reinstall deps when not in prod composer install --prefer-dist --no-progress --no-suggest --no-interaction fi - # Permissions hack because setfacl does not work on Mac and Windows - chown -R www-data var + mkdir -p var/cache var/log + setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var + setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var fi exec docker-php-entrypoint "$@"