mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 00:02:15 +01:00
Added public build
This commit is contained in:
121
docker/prod/Dockerfile
Normal file
121
docker/prod/Dockerfile
Normal file
@@ -0,0 +1,121 @@
|
||||
# Accepted values: 8.3 - 8.2
|
||||
ARG PHP_VERSION=8.3
|
||||
|
||||
ARG DOCKER_FILES_BASE_PATH="docker/prod"
|
||||
|
||||
ARG COMPOSER_VERSION=latest
|
||||
|
||||
###########################################
|
||||
|
||||
FROM composer:${COMPOSER_VERSION} AS vendor
|
||||
|
||||
FROM php:${PHP_VERSION}-cli-bookworm AS base
|
||||
|
||||
LABEL maintainer="solidtime <hello@solidtime.io>"
|
||||
LABEL org.opencontainers.image.title="solidtime"
|
||||
LABEL org.opencontainers.image.description="solidtime is a modern open source timetracker for Freelancers and Agencies"
|
||||
LABEL org.opencontainers.image.source="https://github.com/solidtime-io/solidtime"
|
||||
LABEL org.opencontainers.image.licenses="AGPL"
|
||||
|
||||
ARG WWWUSER=1000
|
||||
ARG WWWGROUP=1000
|
||||
ARG TZ=UTC
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
TERM=xterm-color \
|
||||
WITH_HORIZON=false \
|
||||
WITH_SCHEDULER=false \
|
||||
OCTANE_SERVER=swoole \
|
||||
USER=octane \
|
||||
ROOT=/var/www/html \
|
||||
COMPOSER_FUND=0 \
|
||||
COMPOSER_MAX_PARALLEL_HTTP=24
|
||||
|
||||
WORKDIR ${ROOT}
|
||||
|
||||
SHELL ["/bin/bash", "-eou", "pipefail", "-c"]
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime \
|
||||
&& echo ${TZ} > /etc/timezone
|
||||
|
||||
ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
|
||||
|
||||
RUN apt-get update; \
|
||||
apt-get upgrade -yqq; \
|
||||
apt-get install -yqq --no-install-recommends --show-progress \
|
||||
apt-utils \
|
||||
curl \
|
||||
wget \
|
||||
nano \
|
||||
ncdu \
|
||||
ca-certificates \
|
||||
supervisor \
|
||||
libsodium-dev \
|
||||
# Install PHP extensions
|
||||
&& install-php-extensions \
|
||||
bz2 \
|
||||
pcntl \
|
||||
mbstring \
|
||||
bcmath \
|
||||
sockets \
|
||||
pgsql \
|
||||
pdo_pgsql \
|
||||
opcache \
|
||||
exif \
|
||||
pdo_mysql \
|
||||
zip \
|
||||
intl \
|
||||
gd \
|
||||
redis \
|
||||
rdkafka \
|
||||
memcached \
|
||||
igbinary \
|
||||
ldap \
|
||||
swoole \
|
||||
&& apt-get -y autoremove \
|
||||
&& apt-get clean \
|
||||
&& docker-php-source delete \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
|
||||
&& rm /var/log/lastlog /var/log/faillog
|
||||
|
||||
RUN wget -q "https://github.com/aptible/supercronic/releases/download/v0.2.29/supercronic-linux-amd64" \
|
||||
-O /usr/bin/supercronic \
|
||||
&& chmod +x /usr/bin/supercronic \
|
||||
&& mkdir -p /etc/supercronic \
|
||||
&& echo "*/1 * * * * php ${ROOT}/artisan schedule:run --verbose --no-interaction" > /etc/supercronic/laravel
|
||||
|
||||
RUN userdel --remove --force www-data \
|
||||
&& groupadd --force -g ${WWWGROUP} ${USER} \
|
||||
&& useradd -ms /bin/bash --no-log-init --no-user-group -g ${WWWGROUP} -u ${WWWUSER} ${USER}
|
||||
|
||||
RUN chown -R ${USER}:${USER} ${ROOT} /var/{log,run} \
|
||||
&& chmod -R a+rw /var/{log,run}
|
||||
|
||||
RUN cp ${PHP_INI_DIR}/php.ini-production ${PHP_INI_DIR}/php.ini
|
||||
|
||||
USER ${USER}
|
||||
|
||||
COPY --chown=${USER}:${USER} --from=vendor /usr/bin/composer /usr/bin/composer
|
||||
|
||||
COPY --chown=${USER}:${USER} . .
|
||||
|
||||
RUN mkdir -p \
|
||||
storage/framework/{sessions,views,cache,testing} \
|
||||
storage/logs \
|
||||
bootstrap/cache && chmod -R a+rw storage
|
||||
|
||||
COPY --chown=${USER}:${USER} docker/prod/deployment/supervisord.*.conf /etc/supervisor/conf.d/
|
||||
COPY --chown=${USER}:${USER} docker/prod/deployment/php.ini ${PHP_INI_DIR}/conf.d/99-octane.ini
|
||||
COPY --chown=${USER}:${USER} docker/prod/deployment/start-container /usr/local/bin/start-container
|
||||
|
||||
RUN php artisan storage:link
|
||||
|
||||
RUN chmod +x /usr/local/bin/start-container
|
||||
|
||||
RUN cat docker/prod/deployment/utilities.sh >> ~/.bashrc
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
ENTRYPOINT ["start-container"]
|
||||
|
||||
HEALTHCHECK --start-period=5s --interval=2s --timeout=5s --retries=8 CMD php artisan octane:status || exit 1
|
||||
21
docker/prod/LICENSE
Normal file
21
docker/prod/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Exa Company
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
128
docker/prod/README.md
Normal file
128
docker/prod/README.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Laravel Octane Dockerfile
|
||||
<a href="/LICENSE"><img alt="License" src="https://img.shields.io/github/license/exaco/laravel-octane-dockerfile"></a>
|
||||
<a href="https://github.com/exaco/laravel-octane-dockerfile/releases"><img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/exaco/laravel-octane-dockerfile"></a>
|
||||
<a href="https://github.com/exaco/laravel-octane-dockerfile/pulls"><img alt="GitHub closed pull requests" src="https://img.shields.io/github/issues-pr-closed/exaco/laravel-octane-dockerfile"></a>
|
||||
<a href="https://github.com/exaco/laravel-octane-dockerfile/actions/workflows/tests.yml"><img alt="GitHub Workflow Status" src="https://github.com/exaco/laravel-octane-dockerfile/actions/workflows/roadrunner-test.yml/badge.svg"></a>
|
||||
<a href="https://github.com/exaco/laravel-octane-dockerfile/actions/workflows/tests.yml"><img alt="GitHub Workflow Status" src="https://github.com/exaco/laravel-octane-dockerfile/actions/workflows/swoole-test.yml/badge.svg"></a>
|
||||
<a href="https://github.com/exaco/laravel-octane-dockerfile/actions/workflows/tests.yml"><img alt="GitHub Workflow Status" src="https://github.com/exaco/laravel-octane-dockerfile/actions/workflows/frankenphp-test.yml/badge.svg"></a>
|
||||
|
||||
|
||||
Production-ready Dockerfiles for [Laravel Octane](https://github.com/laravel/octane)
|
||||
powered web services and microservices.
|
||||
|
||||
The Docker configuration provides the following setup:
|
||||
|
||||
- PHP 8.2 and 8.3 official Debian-based images
|
||||
- Preconfigured JIT compiler and OPcache
|
||||
|
||||
## Container modes
|
||||
|
||||
You can run the Docker container in different modes:
|
||||
|
||||
| Mode | `CONTAINER_MODE` | HTTP server |
|
||||
| --------------------- | ---------------- | ------------------- |
|
||||
| HTTP Server (default) | `http` | FrankenPHP / Swoole / RoadRunner |
|
||||
| Horizon | `horizon` | - |
|
||||
| Scheduler | `scheduler` | - |
|
||||
| Worker | `worker` | - |
|
||||
|
||||
## Usage
|
||||
|
||||
### Building Docker image
|
||||
1. Clone this repository:
|
||||
```
|
||||
git clone --depth 1 git@github.com:exaco/laravel-octane-dockerfile.git
|
||||
```
|
||||
2. Copy cloned directory content including `deployment` directory, `Dockerfile`, and `.dockerignore` into your Octane powered Laravel project
|
||||
3. Change the directory to your Laravel project
|
||||
4. Build your image:
|
||||
```
|
||||
docker build -t <image-name>:<tag> -f <your-octane-driver>.Dockerfile .
|
||||
```
|
||||
### Running Docker container
|
||||
|
||||
```bash
|
||||
# HTTP mode
|
||||
docker run -p <port>:80 --rm <image-name>:<tag>
|
||||
|
||||
# Horizon mode
|
||||
docker run -e CONTAINER_MODE=horizon --rm <image-name>:<tag>
|
||||
|
||||
# Scheduler mode
|
||||
docker run -e CONTAINER_MODE=scheduler --rm <image-name>:<tag>
|
||||
|
||||
# HTTP mode with Horizon
|
||||
docker run -e WITH_HORIZON=true -p <port>:80 --rm <image-name>:<tag>
|
||||
|
||||
# HTTP mode with Scheduler
|
||||
docker run -e WITH_SCHEDULER=true -p <port>:80 --rm <image-name>:<tag>
|
||||
|
||||
# HTTP mode with Scheduler and Horizon
|
||||
docker run -e WITH_SCHEDULER=true -e WITH_HORIZON=true -p <port>:80 --rm <image-name>:<tag>
|
||||
|
||||
# Worker mode
|
||||
docker run -e CONTAINER_MODE=worker -e WORKER_COMMAND="php /var/www/html/artisan foo:bar" --rm <image-name>:<tag>
|
||||
|
||||
# Running a single command
|
||||
docker run --rm <image-name>:<tag> php artisan about
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Recommended `Swoole` options in `octane.php`
|
||||
|
||||
```php
|
||||
// config/octane.php
|
||||
|
||||
return [
|
||||
'swoole' => [
|
||||
'options' => [
|
||||
'http_compression' => true,
|
||||
'http_compression_level' => 6, // 1 - 9
|
||||
'compression_min_length' => 20,
|
||||
'package_max_length' => 20 * 1024 * 1024, // 20MB
|
||||
'open_http2_protocol' => true,
|
||||
'document_root' => public_path(),
|
||||
'enable_static_handler' => true,
|
||||
]
|
||||
]
|
||||
];
|
||||
```
|
||||
|
||||
## Utilities
|
||||
|
||||
Also, some useful Bash functions and aliases are added in `utilities.sh` that maybe help.
|
||||
|
||||
## Notes
|
||||
|
||||
- Laravel Octane logs request information only in the `local` environment.
|
||||
- Please be aware of `.dockerignore` content
|
||||
|
||||
## ToDo
|
||||
- [x] Add support for PHP 8.3
|
||||
- [x] Add support for worker mode
|
||||
- [ ] Build assets with Bun
|
||||
- [ ] Create standalone and self-executable app
|
||||
- [x] Add support for Horizon
|
||||
- [x] Add support for RoadRunner
|
||||
- [x] Add support for FrankenPHP
|
||||
- [x] Add support for the full-stack apps (Front-end assets)
|
||||
- [ ] Add support `testing` environment and CI
|
||||
- [x] Add support for the Laravel scheduler
|
||||
- [ ] Add support for Laravel Dusk
|
||||
- [x] Support more PHP extensions
|
||||
- [x] Add tests
|
||||
- [ ] Add Alpine-based images
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing! If you find an issue, or have a better way to do something, feel free to open an
|
||||
issue, or a PR.
|
||||
|
||||
## Credits
|
||||
- [SMortexa](https://github.com/smortexa)
|
||||
- [All contributors](https://github.com/exaco/laravel-octane-dockerfile/graphs/contributors)
|
||||
|
||||
## License
|
||||
|
||||
This repository is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
29
docker/prod/deployment/php.ini
Normal file
29
docker/prod/deployment/php.ini
Normal file
@@ -0,0 +1,29 @@
|
||||
[PHP]
|
||||
post_max_size = 100M
|
||||
upload_max_filesize = 100M
|
||||
expose_php = 0
|
||||
realpath_cache_size = 16M
|
||||
realpath_cache_ttl = 360
|
||||
|
||||
[Opcache]
|
||||
opcache.enable = 1
|
||||
opcache.enable_cli = 1
|
||||
opcache.memory_consumption = 256M
|
||||
opcache.use_cwd = 0
|
||||
opcache.max_file_size = 0
|
||||
opcache.max_accelerated_files = 32531
|
||||
opcache.validate_timestamps = 0
|
||||
opcache.file_update_protection = 0
|
||||
opcache.interned_strings_buffer = 16
|
||||
opcache.file_cache = 60
|
||||
|
||||
[JIT]
|
||||
opcache.jit_buffer_size = 128M
|
||||
opcache.jit = function
|
||||
opcache.jit_prof_threshold = 0.001
|
||||
opcache.jit_max_root_traces = 2048
|
||||
opcache.jit_max_side_traces = 256
|
||||
|
||||
[zlib]
|
||||
zlib.output_compression = On
|
||||
zlib.output_compression_level = 9
|
||||
33
docker/prod/deployment/start-container
Normal file
33
docker/prod/deployment/start-container
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
container_mode=${CONTAINER_MODE:-http}
|
||||
octane_server=${OCTANE_SERVER}
|
||||
echo "Container mode: $container_mode"
|
||||
|
||||
initialStuff() {
|
||||
php artisan optimize:clear; \
|
||||
php artisan event:cache; \
|
||||
php artisan config:cache; \
|
||||
php artisan route:cache;
|
||||
}
|
||||
|
||||
if [ "$1" != "" ]; then
|
||||
exec "$@"
|
||||
elif [ ${container_mode} = "http" ]; then
|
||||
echo "Octane Server: $octane_server"
|
||||
initialStuff
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.swoole.conf
|
||||
elif [ ${container_mode} = "horizon" ]; then
|
||||
initialStuff
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.horizon.conf
|
||||
elif [ ${container_mode} = "scheduler" ]; then
|
||||
initialStuff
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.scheduler.conf
|
||||
elif [ ${container_mode} = "worker" ]; then
|
||||
initialStuff
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.worker.conf
|
||||
else
|
||||
echo "Container mode mismatched."
|
||||
exit 1
|
||||
fi
|
||||
17
docker/prod/deployment/supervisord.horizon.conf
Normal file
17
docker/prod/deployment/supervisord.horizon.conf
Normal file
@@ -0,0 +1,17 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=%(ENV_USER)s
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:horizon]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php %(ENV_ROOT)s/artisan horizon
|
||||
user=%(ENV_USER)s
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
stopwaitsecs=3600
|
||||
27
docker/prod/deployment/supervisord.scheduler.conf
Normal file
27
docker/prod/deployment/supervisord.scheduler.conf
Normal file
@@ -0,0 +1,27 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=%(ENV_USER)s
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:scheduler]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=supercronic -overlapping /etc/supercronic/laravel
|
||||
user=%(ENV_USER)s
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:clear-scheduler-cache]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php %(ENV_ROOT)s/artisan schedule:clear-cache
|
||||
user=%(ENV_USER)s
|
||||
autostart=true
|
||||
autorestart=false
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
42
docker/prod/deployment/supervisord.swoole.conf
Normal file
42
docker/prod/deployment/supervisord.swoole.conf
Normal file
@@ -0,0 +1,42 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=%(ENV_USER)s
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:octane]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php %(ENV_ROOT)s/artisan octane:start --server=swoole --host=0.0.0.0 --port=8000
|
||||
user=%(ENV_USER)s
|
||||
autostart=true
|
||||
autorestart=true
|
||||
environment=LARAVEL_OCTANE="1"
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:horizon]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php %(ENV_ROOT)s/artisan horizon
|
||||
user=%(ENV_USER)s
|
||||
autostart=%(ENV_WITH_HORIZON)s
|
||||
autorestart=true
|
||||
stdout_logfile=%(ENV_ROOT)s/horizon.log
|
||||
stopwaitsecs=3600
|
||||
|
||||
[program:scheduler]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=supercronic -overlapping /etc/supercronic/laravel
|
||||
user=%(ENV_USER)s
|
||||
autostart=%(ENV_WITH_SCHEDULER)s
|
||||
autorestart=true
|
||||
stdout_logfile=%(ENV_ROOT)s/scheduler.log
|
||||
|
||||
[program:clear-scheduler-cache]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php %(ENV_ROOT)s/artisan schedule:clear-cache
|
||||
user=%(ENV_USER)s
|
||||
autostart=%(ENV_WITH_SCHEDULER)s
|
||||
autorestart=false
|
||||
stdout_logfile=%(ENV_ROOT)s/scheduler.log
|
||||
16
docker/prod/deployment/supervisord.worker.conf
Normal file
16
docker/prod/deployment/supervisord.worker.conf
Normal file
@@ -0,0 +1,16 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=%(ENV_USER)s
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:worker]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=%(ENV_WORKER_COMMAND)s
|
||||
user=%(ENV_USER)s
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
12
docker/prod/deployment/utilities.sh
Normal file
12
docker/prod/deployment/utilities.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
tinker() {
|
||||
if [ -z "$1" ]; then
|
||||
php artisan tinker
|
||||
else
|
||||
php artisan tinker --execute="\"dd($1);\""
|
||||
fi
|
||||
}
|
||||
|
||||
# Commonly used aliases
|
||||
alias ..="cd .."
|
||||
alias ...="cd ../.."
|
||||
alias art="php artisan"
|
||||
Reference in New Issue
Block a user