├── captain-definition ├── .deploy ├── config │ ├── crontab │ ├── php │ │ └── local.ini │ ├── Caddyfile │ └── supervisor.conf ├── entrypoint.sh └── Dockerfile ├── LICENSE └── README.md /captain-definition: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion" :2 , 3 | "dockerfilePath" : "./.deploy/Dockerfile" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /.deploy/config/crontab: -------------------------------------------------------------------------------- 1 | * * * * * /usr/local/bin/php /srv/app/artisan schedule:run > /proc/1/fd/1 2>/proc/1/fd/2 2 | -------------------------------------------------------------------------------- /.deploy/config/php/local.ini: -------------------------------------------------------------------------------- 1 | memory_limit = 512M 2 | max_execution_time = 30 3 | upload_max_filesize = 30M 4 | post_max_size = 35M 5 | -------------------------------------------------------------------------------- /.deploy/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "🎬 entrypoint.sh: [$(whoami)] [PHP $(php -r 'echo phpversion();')]" 4 | 5 | composer dump-autoload --no-interaction --no-dev --optimize 6 | 7 | echo "🎬 artisan commands" 8 | 9 | # 💡 Group into a custom command e.g. php artisan app:on-deploy 10 | php artisan migrate --no-interaction --force 11 | 12 | echo "🎬 start supervisord" 13 | 14 | supervisord -c $LARAVEL_PATH/.deploy/config/supervisor.conf 15 | -------------------------------------------------------------------------------- /.deploy/config/Caddyfile: -------------------------------------------------------------------------------- 1 | :80 { 2 | root * /srv/app/public 3 | 4 | @websockets { 5 | header Connection *upgrade* 6 | header Upgrade websocket 7 | } 8 | reverse_proxy @websockets 127.0.0.1:6001 { 9 | header_down -X-Powered-By 10 | } 11 | 12 | redir /index.php / 308 13 | redir /index.php/ / 308 14 | route /index.php/* { 15 | uri strip_prefix /index.php 16 | redir {path} 308 17 | } 18 | 19 | php_fastcgi 127.0.0.1:9000 20 | encode gzip 21 | header -X-Powered-By 22 | file_server 23 | log 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jack Bryce-Smith 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.deploy/config/supervisor.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | logfile=/dev/null 3 | logfile_maxbytes=0 4 | logfile_backups=0 5 | loglevel=info 6 | nodaemon=true 7 | 8 | [program:php-fpm] 9 | command=php-fpm --nodaemonize 10 | autorestart=true 11 | stdout_events_enabled=true 12 | stderr_events_enabled=true 13 | stdout_logfile_maxbytes=0 14 | stderr_logfile_maxbytes=0 15 | stdout_logfile=/dev/stdout 16 | stderr_logfile=/dev/stderr 17 | 18 | [program:caddy] 19 | command=caddy run --config %(ENV_LARAVEL_PATH)s/.deploy/config/Caddyfile 20 | autorestart=true 21 | stdout_events_enabled=true 22 | stderr_events_enabled=true 23 | stdout_logfile_maxbytes=0 24 | stderr_logfile_maxbytes=0 25 | stdout_logfile=/dev/stdout 26 | stderr_logfile=/dev/stderr 27 | 28 | [program:cron] 29 | command=crond -l 2 -f 30 | autorestart=true 31 | 32 | ; [program:horizon] 33 | ; command=php %(ENV_LARAVEL_PATH)s/artisan horizon 34 | ; autorestart=true 35 | ; stdout_events_enabled=true 36 | ; stderr_events_enabled=true 37 | ; stdout_logfile_maxbytes=0 38 | ; stderr_logfile_maxbytes=0 39 | ; stdout_logfile=/dev/stdout 40 | ; stderr_logfile=/dev/stderr 41 | ; stopwaitsecs=3600 42 | 43 | ; [program:websockets] 44 | ; command=php %(ENV_LARAVEL_PATH)s/artisan websockets:serve --port=6001 45 | ; numprocs=1 46 | ; autorestart=true 47 | ; stdout_events_enabled=true 48 | ; stderr_events_enabled=true 49 | ; stdout_logfile_maxbytes=0 50 | ; stderr_logfile_maxbytes=0 51 | ; stdout_logfile=/dev/stdout 52 | ; stderr_logfile=/dev/stderr 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | +
6 |
7 |
8 |
9 |
14 | Template to deploy a Laravel app to a server managed by CapRover. 15 |
16 | 17 |18 | 19 | jack.bryce-smith.com/💡/laravel-docker-caprover 20 | 21 |
22 | 23 | ## Features 24 | 25 | - 🐳 Lightweight [PHP](https://github.com/jackbrycesmith/laravel-caprover-template/blob/master/.deploy/Dockerfile#L1) image with [common extensions](https://github.com/jackbrycesmith/laravel-caprover-template/blob/master/.deploy/Dockerfile#L21) 26 | - [Overridable PHP version](https://github.com/jackbrycesmith/laravel-caprover-template/pull/13) 27 | - Add other required extensions easily; [thanks to mlocati/docker-php-extension-installer](https://github.com/mlocati/docker-php-extension-installer) 28 | - 📦 [Installs composer dependencies](https://github.com/jackbrycesmith/laravel-caprover-template/blob/master/.deploy/Dockerfile#L30); cached between builds if no changes 29 | - ⚡️ Served via [Caddy 2](https://github.com/caddyserver/caddy) 30 | - ⏰ [Setup to call](https://github.com/jackbrycesmith/laravel-caprover-template/blob/master/.deploy/Dockerfile#L11) the [Laravel command scheduler](https://laravel.com/docs/7.x/scheduling) 31 | - 🛰 Straightforward websockets support 32 | - 💪 [Services will restart](https://github.com/jackbrycesmith/laravel-caprover-template/blob/master/.deploy/config/supervisor.conf) thanks to [supervisord](https://github.com/ochinchina/supervisord) 33 | 34 | ## Usage 35 | 36 | 1. [Install Laravel](https://laravel.com/docs/installation) 37 | > *e.g. Zsh one-liner with the [Laravel Installer](https://github.com/laravel/installer):* 38 | >laravel new my-app --prompt-jetstream && mv my-app/*(DN) ./ && rm -rf my-app
39 | 2. jack.bryce-smith.com/💡/laravel-docker-caprover
40 | 3. [Deploy to CapRover](https://caprover.com/docs/deployment-methods.html), e.g. `caprover deploy`
41 |
--------------------------------------------------------------------------------
/.deploy/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG PHP_VERSION=${PHP_VERSION:-7.4}
2 | FROM php:${PHP_VERSION}-fpm-alpine AS php-system-setup
3 |
4 | # Install system dependencies
5 | RUN apk add --no-cache dcron busybox-suid libcap curl zip unzip git
6 |
7 | # Install PHP extensions
8 | COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
9 | RUN install-php-extensions intl bcmath gd pdo_mysql pdo_pgsql opcache redis uuid exif pcntl zip
10 |
11 | # Install supervisord implementation
12 | COPY --from=ochinchina/supervisord:latest /usr/local/bin/supervisord /usr/local/bin/supervisord
13 |
14 | # Install caddy
15 | COPY --from=caddy:2.2.1 /usr/bin/caddy /usr/local/bin/caddy
16 | RUN setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy
17 |
18 | # Install composer
19 | COPY --from=composer/composer:2 /usr/bin/composer /usr/local/bin/composer
20 |
21 | FROM php-system-setup AS app-setup
22 |
23 | # Set working directory
24 | ENV LARAVEL_PATH=/srv/app
25 | WORKDIR $LARAVEL_PATH
26 |
27 | # Add non-root user: 'app'
28 | ARG NON_ROOT_GROUP=${NON_ROOT_GROUP:-app}
29 | ARG NON_ROOT_USER=${NON_ROOT_USER:-app}
30 | RUN addgroup -S $NON_ROOT_GROUP && adduser -S $NON_ROOT_USER -G $NON_ROOT_GROUP
31 | RUN addgroup $NON_ROOT_USER wheel
32 |
33 | # Set cron job
34 | COPY ./.deploy/config/crontab /etc/crontabs/$NON_ROOT_USER
35 | RUN chmod 777 /usr/sbin/crond
36 | RUN chown -R $NON_ROOT_USER:$NON_ROOT_GROUP /etc/crontabs/$NON_ROOT_USER && setcap cap_setgid=ep /usr/sbin/crond
37 |
38 | # Switch to non-root 'app' user & install app dependencies
39 | COPY composer.json composer.lock ./
40 | RUN chown -R $NON_ROOT_USER:$NON_ROOT_GROUP $LARAVEL_PATH
41 | USER $NON_ROOT_USER
42 | RUN composer install --prefer-dist --no-scripts --no-dev --no-autoloader
43 | RUN rm -rf /home/$NON_ROOT_USER/.composer
44 |
45 | # Copy app
46 | COPY --chown=$NON_ROOT_USER:$NON_ROOT_GROUP . $LARAVEL_PATH/
47 | COPY ./.deploy/config/php/local.ini /usr/local/etc/php/conf.d/local.ini
48 |
49 | # Set any ENVs
50 | ARG APP_KEY=${APP_KEY}
51 | ARG APP_NAME=${APP_NAME}
52 | ARG APP_URL=${APP_URL}
53 | ARG APP_ENV=${APP_ENV}
54 | ARG APP_DEBUG=${APP_DEBUG}
55 |
56 | ARG LOG_CHANNEL=${LOG_CHANNEL}
57 |
58 | ARG DB_CONNECTION=${DB_CONNECTION}
59 | ARG DB_HOST=${DB_HOST}
60 | ARG DB_PORT=${DB_PORT}
61 | ARG DB_DATABASE=${DB_DATABASE}
62 | ARG DB_USERNAME=${DB_USERNAME}
63 | ARG DB_PASSWORD=${DB_PASSWORD}
64 |
65 | ARG BROADCAST_DRIVER=${BROADCAST_DRIVER}
66 | ARG CACHE_DRIVER=${CACHE_DRIVER}
67 | ARG QUEUE_CONNECTION=${QUEUE_CONNECTION}
68 | ARG SESSION_DRIVER=${SESSION_DRIVER}
69 | ARG SESSION_LIFETIME=${SESSION_LIFETIME}
70 |
71 | ARG REDIS_HOST=${REDIS_HOST}
72 | ARG REDIS_PASSWORD=${REDIS_PASSWORD}
73 | ARG REDIS_PORT=${REDIS_PORT}
74 |
75 | ARG MAIL_MAILER=${MAIL_MAILER}
76 | ARG MAIL_HOST=${MAIL_HOST}
77 | ARG MAIL_PORT=${MAIL_PORT}
78 | ARG MAIL_USERNAME=${MAIL_USERNAME}
79 | ARG MAIL_PASSWORD=${MAIL_PASSWORD}
80 | ARG MAIL_ENCRYPTION=${MAIL_ENCRYPTION}
81 | ARG MAIL_FROM_ADDRESS=${MAIL_FROM_ADDRESS}
82 | ARG MAIL_ENCRYPTION=${MAIL_ENCRYPTION}
83 | ARG MAIL_FROM_NAME=${APP_NAME}
84 |
85 | ARG PUSHER_APP_ID=${PUSHER_APP_ID}
86 | ARG PUSHER_APP_KEY=${PUSHER_APP_KEY}
87 | ARG PUSHER_APP_SECRET=${PUSHER_APP_SECRET}
88 | ARG PUSHER_APP_CLUSTER=${PUSHER_APP_CLUSTER}
89 |
90 | # Start app
91 | EXPOSE 80
92 | COPY ./.deploy/entrypoint.sh /
93 |
94 | ENTRYPOINT ["sh", "/entrypoint.sh"]
95 |
--------------------------------------------------------------------------------