diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d55992067..91546911f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -6,11 +6,15 @@ - Clone the repository - Ensure your Docker daemon is running -- Launch `docker-compose up` +- Copy `docker/php/env.example` to `docker/php/env` and customize +- Launch `docker-compose run --rm php composer install` to bootstrap php dependencies +- Launch `docker-compose run --rm php bin/console wallabag:install` to bootstrap your installation +- Launch `docker-compose run --rm php yarn install` to bootstrap dependencies for the frontend +- Launch `docker-compose run --rm php yarn build:dev` to build assets for the frontend +- Launch `docker-compose up -d` to start the stack You'll then have: -- a web server (nginx) -- a PHP daemon (using FPM) +- a PHP daemon with standalone web server - a Redis database (to handle imports) - a SQLite database to store articles diff --git a/.gitignore b/.gitignore index 3d9464663..100db94e0 100644 --- a/.gitignore +++ b/.gitignore @@ -35,16 +35,15 @@ web/uploads/ /build /coverage +# Development +docker/php/env + # Composer PHAR /composer.phar # Data for wallabag data/db/wallabag*.sqlite -# Docker container logs and data -docker/logs/ -docker/data/ - # assets stuff node_modules/ bin diff --git a/docker-compose.yml b/docker-compose.yml index 34eb09560..c92bd2c0a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,52 +1,64 @@ -version: '2' +version: '3.8' services: - nginx: - image: nginx:alpine - ports: - - "8000:80" - volumes: - - ./docker/nginx/nginx.conf:/nginx.conf - - ./docker/logs/nginx:/var/log/nginx - - .:/var/www/html - links: - - php:php - command: nginx -c /nginx.conf php: build: context: docker/php - args: - # Set here your timezone using one of this: https://php.net/manual/en/timezones.php - timezone: 'Europe/Monaco' - ports: - - "9000:9000" + # Use target 'rootless' if you run rootless Docker + target: default volumes: - .:/var/www/html - #links: - # - "postgres:rdbms" - # - "mariadb:rdbms" + # Volumes for data-related folders + - assets:/var/www/html/web/assets + - data:/var/www/html/data + - cache:/var/www/.cache + # Uncomment the following volume if you run rootless Docker + # A limitation blocks permissions on root docker, see + # https://github.com/moby/moby/issues/40881 + # - type: tmpfs + # target: /var/www/html/var/cache + # Override third-party libraries for dev + # - ../graby-site-config:/var/www/html/vendor/j0k3r/graby-site-config + # - ../php-readability:/var/www/html/vendor/j0k3r/php-readability + # - ../graby:/var/www/html/vendor/j0k3r/graby + # - ../HTMLawed:/var/www/html/vendor/fossar/htmlawed + # - ../PHPePub:/var/www/html/vendor/wallabag/phpepub + # - ../guzzle-site-authenticator:/var/www/html/vendor/bdunogier/guzzle-site-authenticator env_file: + # Copy docker/php/env.example to docker/php/env and customize - ./docker/php/env - # Comment non-used DBMS lines - # If all DBMS are commented out, sqlite will be used as default - # - ./docker/postgres/env + # Uncomment the database engine you want, it will use sqlite if both are commented # - ./docker/mariadb/env + # - ./docker/postgres/env + # Uncomment to enable Xdebug + # - ./docker/php/xdebug + ports: + - 8000:8000 + # Uncomment to permit Xdebug remote session + # - 9000:9000 + depends_on: + # - mariadb + # - postgres + - redis # postgres: - # image: postgres:11-alpine - # ports: - # - "5432:5432" - # volumes: - # - ./docker/data/pgsql:/var/lib/postgresql/data - # env_file: - # - ./docker/postgres/env + # image: postgres:11-alpine + # volumes: + # - db-data:/var/lib/postgresql/data + # env_file: + # - ./docker/postgres/env + # healthcheck: + # test: ["CMD-SHELL", "pg_isready -q || exit 1"] + # interval: 10s + # timeout: 3s + # retries: 3 # mariadb: # image: mariadb:10 # ports: # - "3306:3306" # volumes: - # - ./docker/data/mariadb:/var/lib/mysql + # - db-data:/var/lib/mysql # env_file: # - ./docker/mariadb/env @@ -56,6 +68,19 @@ services: # - "15672:15672" redis: - image: redis:4-alpine - ports: - - "6379:6379" + image: redis:6-alpine + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 3s + retries: 3 + +volumes: + db-data: + driver: local + assets: + driver: local + data: + driver: local + cache: + driver: local diff --git a/docker/mariadb/env b/docker/mariadb/env index 87556a15d..afb16c5ed 100644 --- a/docker/mariadb/env +++ b/docker/mariadb/env @@ -2,9 +2,9 @@ MYSQL_ROOT_PASSWORD=wallaroot MYSQL_USER=wallabag MYSQL_PASSWORD=wallapass MYSQL_DATABASE=wallabag -SYMFONY__ENV__DATABASE_DRIVER=pdo_mysql -SYMFONY__ENV__DATABASE_HOST=rdbms -SYMFONY__ENV__DATABASE_PORT=3306 -SYMFONY__ENV__DATABASE_NAME=wallabag -SYMFONY__ENV__DATABASE_USER=wallabag -SYMFONY__ENV__DATABASE_PASSWORD=wallapass +DATABASE_DRIVER=pdo_mysql +DATABASE_HOST=mysql +DATABASE_PORT=3306 +DATABASE_NAME=wallabag +DATABASE_USER=wallabag +DATABASE_PASSWORD=wallapass diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf deleted file mode 100644 index 7e82a0f89..000000000 --- a/docker/nginx/nginx.conf +++ /dev/null @@ -1,89 +0,0 @@ -user nginx; -worker_processes 1; -pid /var/run/nginx.pid; - -events { - worker_connections 2048; - multi_accept on; - use epoll; -} - -http { - - 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; - - server_tokens off; - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 15; - types_hash_max_size 2048; - include /etc/nginx/mime.types; - default_type application/octet-stream; - access_log off; - error_log off; - gzip on; - gzip_disable "msie6"; - open_file_cache max=100; - - - upstream php-upstream { - server php:9000; - } - - server { - #server_name domain.tld www.domain.tld; - root /var/www/html/web; - - location / { - # try to serve file directly, fallback to app.php - try_files $uri /app.php$is_args$args; - } - # DEV - # This rule should only be placed on your development environment - # In production, don't include this and don't deploy app_dev.php or config.php - location ~ ^/(app_dev|config)\.php(/|$) { - fastcgi_pass php-upstream; - fastcgi_split_path_info ^(.+\.php)(/.*)$; - include fastcgi_params; - # When you are using symlinks to link the document root to the - # current version of your application, you should pass the real - # application path instead of the path to the symlink to PHP - # FPM. - # Otherwise, PHP's OPcache may not properly detect changes to - # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126 - # for more information). - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - fastcgi_param DOCUMENT_ROOT $realpath_root; - } - # PROD - location ~ ^/app\.php(/|$) { - fastcgi_pass php-upstream; - fastcgi_split_path_info ^(.+\.php)(/.*)$; - include fastcgi_params; - # When you are using symlinks to link the document root to the - # current version of your application, you should pass the real - # application path instead of the path to the symlink to PHP - # FPM. - # Otherwise, PHP's OPcache may not properly detect changes to - # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126 - # for more information). - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - fastcgi_param DOCUMENT_ROOT $realpath_root; - # Prevents URIs that include the front controller. This will 404: - # http://domain.tld/app.php/some-path - # Remove the internal directive to allow URIs like this - internal; - } - - error_log /var/log/nginx/project_error.log; - access_log /var/log/nginx/project_access.log; - } - -} - -daemon off; diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index 171e12fc9..0deb6307d 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -1,8 +1,19 @@ -FROM php:7.2-fpm +FROM php:8.0-fpm AS rootless -# Default timezone. To change it, use the argument in the docker-compose.yml file -ARG timezone='Europe/Paris' -ARG memorylimit='512M' +ARG DEBIAN_FRONTEND=noninteractive +ARG NODE_VERSION=14 + +RUN apt-get update \ + && apt-get install -y \ + ca-certificates \ + curl \ + gnupg \ + lsb-release \ + openssl \ + software-properties-common + +RUN curl 'https://deb.nodesource.com/gpgkey/nodesource.gpg.key' | apt-key add - \ + && echo "deb https://deb.nodesource.com/node_${NODE_VERSION}.x $(lsb_release -cs) main" > /etc/apt/sources.list.d/nodesource.list RUN apt-get update && apt-get install -y \ libmcrypt-dev \ @@ -15,26 +26,71 @@ RUN apt-get update && apt-get install -y \ imagemagick \ libmagickwand-dev \ libtidy-dev \ - git -RUN docker-php-ext-install \ - iconv \ - mbstring \ + libonig-dev \ + libzip-dev \ + libfreetype6-dev \ + zlib1g-dev \ + git \ + build-essential \ + nodejs +RUN docker-php-ext-configure gd --with-freetype --with-jpeg +RUN docker-php-ext-install -j "$(nproc)" \ + bcmath \ gd \ + gettext \ + iconv \ intl \ + mbstring \ + opcache \ pdo \ pdo_mysql \ pdo_pgsql \ pdo_sqlite \ sockets \ tidy \ - bcmath \ zip -RUN printf "\n" | pecl install imagick && docker-php-ext-enable imagick +RUN pecl install redis; \ + pecl install imagick; \ + pecl install xdebug; \ + docker-php-ext-enable \ + redis \ + imagick \ + xdebug \ + ; -RUN echo "date.timezone="$timezone > /usr/local/etc/php/conf.d/date_timezone.ini -RUN echo "memory_limit ="$memorylimit > /usr/local/etc/php/conf.d/memory_limit.ini +RUN npm install -g yarn -RUN usermod -u 1000 www-data +RUN curl -L -o /usr/local/bin/envsubst https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m`; \ + chmod +x /usr/local/bin/envsubst -CMD ["php-fpm"] +COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer + +COPY entrypoint.sh /entrypoint.sh +COPY config/ /opt/wallabag/config/ + +RUN mkdir -p \ + /var/www/html/app/config/ \ + /var/www/html/var/cache \ + /var/www/html/web/assets \ + /var/www/html/data \ + /var/www/.cache + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["php", "bin/console", "--env=dev", "server:run", "0.0.0.0:8000"] + +FROM rootless AS default + +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupmod -g 1000 www-data ; \ + usermod -u ${USER_UID} -g www-data www-data ; \ + touch /usr/local/etc/php/conf.d/wallabag-php.ini \ + /var/www/.yarnrc ; \ + chown -R www-data: /var/www/html \ + /usr/local/etc/php/conf.d/wallabag-php.ini \ + /var/www/.cache \ + /var/www/.yarnrc + +USER www-data diff --git a/docker/php/config/parameters.yml b/docker/php/config/parameters.yml new file mode 100644 index 000000000..a647aa589 --- /dev/null +++ b/docker/php/config/parameters.yml @@ -0,0 +1,62 @@ +parameters: + database_driver: ${DATABASE_DRIVER:-pdo_sqlite} + database_driver_class: ${DATABASE_DRIVER_CLASS:-~} + database_host: ${DATABASE_HOST:-127.0.0.1} + database_port: ${DATABASE_PORT:-~} + database_name: ${DATABASE_NAME:-symfony} + database_user: ${DATABASE_USER:-root} + database_password: ${DATABASE_PASSWORD:-~} + database_path: ${DATABASE_PATH:-"%kernel.root_dir%/data/wallabag.sqlite"} + database_table_prefix: wallabag_ + database_socket: null + database_charset: ${DATABASE_CHARSET:-utf8} + + domain_name: ${DOMAIN_NAME:-https://www.example.com} + server_name: ${SERVER_NAME:-"Your wallabag instance"} + + mailer_transport: ${MAILER_TRANSPORT:-smtp} + mailer_user: ${MAILER_USER:-~} + mailer_password: ${MAILER_PASSWORD:-~} + mailer_host: ${MAILER_HOST:-127.0.0.1} + mailer_port: ${MAILER_PORT:-25} + mailer_encryption: ${MAILER_ENCRYPTION:-~} + mailer_auth_mode: ${MAILER_AUTH_MODE:-~} + + locale: ${LOCALE:-en} + + # A secret key that's used to generate certain security-related tokens + secret: ${SECRET:-~} + + # two factor stuff + twofactor_auth: ${TWOFACTOR_AUTH:-true} + twofactor_sender: ${TWOFACTOR_SENDER:-no-reply@wallabag.org} + + # fosuser stuff + fosuser_registration: ${FOSUSER_REGISTRATION:-true} + fosuser_confirmation: ${FOSUSER_CONFIRMATION:-true} + + fos_oauth_server_access_token_lifetime: 3600 + fos_oauth_server_refresh_token_lifetime: 1209600 + + from_email: ${FROM_EMAIL:-wallabag@example.com} + + rss_limit: 50 + + # RabbitMQ processing + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: guest + rabbitmq_password: guest + rabbitmq_prefetch_count: 10 + + # Redis processing + redis_scheme: ${REDIS_SCHEME:-tcp} + redis_host: ${REDIS_HOST:-redis} + redis_port: ${REDIS_PORT:-6379} + redis_path: ${REDIS_PATH:-~} + redis_password: ${REDIS_PASSWORD:-~} + + # Sentry + sentry_dsn: ${SENTRY_DSN:-~} + + session_handler: ${SESSION_HANDLER:-session.handler.native_file} diff --git a/docker/php/config/wallabag-php.ini b/docker/php/config/wallabag-php.ini new file mode 100644 index 000000000..ff19e4484 --- /dev/null +++ b/docker/php/config/wallabag-php.ini @@ -0,0 +1,10 @@ +memory_limit = ${PHP_MEMORY_LIMIT:-512M} + +max_execution_time = ${PHP_MAX_EXECUTION_TIME:-60} + +date.time = ${PHP_TIMEZONE:-Europe/Paris} + +session.save_handler = ${PHP_SESSION_HANDLER:-files} +session.save_path = "${PHP_SESSION_SAVE_PATH:-}" + +upload_max_filesize = 10M diff --git a/docker/php/entrypoint.sh b/docker/php/entrypoint.sh new file mode 100755 index 000000000..e147ed311 --- /dev/null +++ b/docker/php/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +envsubst < /opt/wallabag/config/wallabag-php.ini > /usr/local/etc/php/conf.d/wallabag-php.ini +envsubst < /opt/wallabag/config/parameters.yml > /var/www/html/app/config/parameters.yml + +exec "$@" diff --git a/docker/php/env b/docker/php/env deleted file mode 100644 index 935134fca..000000000 --- a/docker/php/env +++ /dev/null @@ -1,6 +0,0 @@ -SYMFONY__ENV__DATABASE_DRIVER=pdo_sqlite -SYMFONY__ENV__DATABASE_HOST=127.0.0.1 -SYMFONY__ENV__DATABASE_PORT=~ -SYMFONY__ENV__DATABASE_NAME=symfony -SYMFONY__ENV__DATABASE_USER=root -SYMFONY__ENV__DATABASE_PASSWORD=~ diff --git a/docker/php/env.example b/docker/php/env.example new file mode 100644 index 000000000..9a21571dd --- /dev/null +++ b/docker/php/env.example @@ -0,0 +1,13 @@ +DATABASE_DRIVER=pdo_sqlite +DATABASE_HOST=127.0.0.1 +DATABASE_PORT=~ +DATABASE_NAME=symfony +DATABASE_USER=root +DATABASE_PASSWORD=~ +DATABASE_PATH="%kernel.project_dir%/data/wallabag.sqlite" +DOMAIN_NAME=http://localhost:8000 +SECRET=ch4n63m31fy0uc4n +PHP_SESSION_SAVE_PATH=tcp://redis:6379?database=2 +PHP_SESSION_HANDLER=redis +SESSION_HANDLER=~ +TRUSTED_PROXIES=0.0.0.0/0 diff --git a/docker/php/xdebug b/docker/php/xdebug new file mode 100644 index 000000000..1eb876d61 --- /dev/null +++ b/docker/php/xdebug @@ -0,0 +1,2 @@ +XDEBUG_MODE=debug +XDEBUG_TRIGGER=yes \ No newline at end of file diff --git a/docker/postgres/env b/docker/postgres/env index 0dd1adb33..5d9761861 100644 --- a/docker/postgres/env +++ b/docker/postgres/env @@ -1,9 +1,10 @@ POSTGRES_USER=wallabag POSTGRES_PASSWORD=wallapass POSTGRES_DB=wallabag -SYMFONY__ENV__DATABASE_HOST=rdbms -SYMFONY__ENV__DATABASE_PORT=5432 -SYMFONY__ENV__DATABASE_NAME=wallabag -SYMFONY__ENV__DATABASE_USER=wallabag -SYMFONY__ENV__DATABASE_PASSWORD=wallapass -SYMFONY__ENV__DATABASE_DRIVER=pdo_pgsql +DATABASE_HOST=postgres +DATABASE_PORT=5432 +DATABASE_NAME=wallabag +DATABASE_USER=wallabag +DATABASE_PASSWORD=wallapass +DATABASE_DRIVER=pdo_pgsql +DATABASE_PATH=null