mirror of
https://github.com/jikan-me/jikan-rest.git
synced 2025-02-20 11:23:35 +08:00
Merge branch 'master' into feature/new-reviews
This commit is contained in:
commit
2336b7c610
21
.dockerignore
Normal file
21
.dockerignore
Normal file
@ -0,0 +1,21 @@
|
||||
.dockerignore
|
||||
docker/*
|
||||
Makefile
|
||||
docker*.yml
|
||||
Dockerfile
|
||||
bootstrap/cache/*
|
||||
storage/logs/*
|
||||
storage/framework/cache/data/*
|
||||
storage/framework/sessions/*
|
||||
storage/framework/testing/*
|
||||
storage/framework/views/*
|
||||
storage/*.cache
|
||||
vendor
|
||||
node_modules
|
||||
*.log
|
||||
.gitignore
|
||||
.editorconfig
|
||||
.idea
|
||||
.vscode
|
||||
.github
|
||||
.git
|
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@ -11,3 +11,8 @@ updates:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-name: "jikan*"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
|
||||
|
58
.github/workflows/container-base-image-release.yml
vendored
Normal file
58
.github/workflows/container-base-image-release.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
name: Container Base Image Release
|
||||
concurrency: production
|
||||
on:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
release-base-image:
|
||||
runs-on: ubuntu-latest
|
||||
name: Release base container image
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up qemu
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up docker buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
- name: Read metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/jikan-me/jikan-rest-php
|
||||
jikanme/jikan-rest-php
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=sha
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
context: ./docker/base_image/php-8.0
|
||||
# let's use github action cache storage
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
GITHUB_PERSONAL_TOKEN=${{ secrets.GITHUB_TOKEN }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
71
.github/workflows/container-image-release.yml
vendored
Normal file
71
.github/workflows/container-image-release.yml
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
name: Container Image Release
|
||||
concurrency: production
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
release-app-image:
|
||||
runs-on: ubuntu-latest
|
||||
name: Release App container image
|
||||
steps:
|
||||
- name: Check if base container image exists
|
||||
id: baseImageExists
|
||||
run: |
|
||||
GHCR_TOKEN=$(echo ${{ secrets.GITHUB_TOKEN }} | base64)
|
||||
curl --fail -H "Authorization: Bearer ${GHCR_TOKEN}" https://ghcr.io/v2/jikan-me/jikan-rest-php/tags/list | grep -q latest
|
||||
|
||||
- name: Base image existance check failed
|
||||
if: ${{ always() && steps.baseImageExists.outcome == 'failure' }}
|
||||
run: echo "Base image doesn't exist yet. Please run the base image creation workflow first."
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up qemu
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up docker buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
- name: Read metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/jikan-me/jikan-rest
|
||||
jikanme/jikan-rest
|
||||
tags: |
|
||||
type=raw,value=${{ github.ref_name }}
|
||||
type=sha
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
context: .
|
||||
# let's use github action cache storage
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
GITHUB_PERSONAL_TOKEN=${{ secrets.GITHUB_TOKEN }}
|
||||
BASE_IMAGE_VERSION=latest
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
220
.rr.local.unix.yaml
Normal file
220
.rr.local.unix.yaml
Normal file
@ -0,0 +1,220 @@
|
||||
# ---------------------------------------------------------------------------------------------------
|
||||
# WARNING! This file should be used ONLY for local application development. NOT for production usage!
|
||||
# ---------------------------------------------------------------------------------------------------
|
||||
|
||||
# Hint: RR will replace any config options using reference to environment variables,
|
||||
# eg.: `option_key: ${ENVIRONMENT_VARIABLE_NAME}`.
|
||||
|
||||
# RR configuration version
|
||||
version: "2.7"
|
||||
|
||||
# Remote Procedures Calling (docs: https://roadrunner.dev/docs/beep-beep-rpc)
|
||||
# Is used for connecting to RoadRunner server from your PHP workers.
|
||||
rpc:
|
||||
# TCP address:port for listening.
|
||||
#
|
||||
# Default: "tcp://127.0.0.1:6001"
|
||||
listen: tcp://127.0.0.1:6001
|
||||
|
||||
# Application server settings (docs: https://roadrunner.dev/docs/php-worker)
|
||||
server:
|
||||
# Worker starting command, with any required arguments.
|
||||
#
|
||||
# This option is required.
|
||||
command: "php -dxdebug.start_with_request=trigger -dxdebug.mode=debug -dxdebug.client_port=9000 -dxdebug.client_host=127.0.0.1 -didekey=PHPSTORM ./vendor/bin/rr-worker start --relay-dsn unix:///var/run/rr/rr-relay.sock"
|
||||
env:
|
||||
- XDEBUG_SESSION: "1"
|
||||
|
||||
## Environment variables for the worker processes.
|
||||
##
|
||||
## Default: <empty map>
|
||||
#env:
|
||||
# - SOME_KEY: "SOME_VALUE"
|
||||
# - SOME_KEY2: "SOME_VALUE2"
|
||||
|
||||
# Worker relay can be: "pipes", TCP (eg.: tcp://127.0.0.1:6001), or socket (eg.: unix:///var/run/rr-relay.sock).
|
||||
#
|
||||
# Default: "pipes"
|
||||
relay: "unix:///var/run/rr/rr-relay.sock"
|
||||
|
||||
# Timeout for relay connection establishing (only for socket and TCP port relay).
|
||||
#
|
||||
# Default: 60s
|
||||
relay_timeout: 60s
|
||||
|
||||
# HTTP plugin settings.
|
||||
http:
|
||||
# Host and port to listen on (eg.: `127.0.0.1:8080`).
|
||||
#
|
||||
# This option is required.
|
||||
address: 0.0.0.0:8080
|
||||
|
||||
# HTTP access logs
|
||||
#
|
||||
# Default: false
|
||||
access_logs: true
|
||||
|
||||
# Maximal incoming request size in megabytes. Zero means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_request_size: 256
|
||||
|
||||
# Middlewares for the http plugin, order is important. Allowed values is: "headers", "gzip".
|
||||
#
|
||||
# Default value: []
|
||||
middleware: ["static", "headers", "gzip"]
|
||||
|
||||
# File uploading settings.
|
||||
uploads:
|
||||
# Directory for file uploads. Empty value means to use $TEMP based on your OS.
|
||||
#
|
||||
# Default: ""
|
||||
dir: "/tmp"
|
||||
|
||||
# Deny files with the following extensions to upload.
|
||||
#
|
||||
# Default: [".php", ".exe", ".bat"]
|
||||
forbid: [".php", ".exe", ".bat", ".sh"]
|
||||
|
||||
# Settings for "headers" middleware (docs: https://roadrunner.dev/docs/http-headers).
|
||||
headers:
|
||||
# Automatically add headers to every response.
|
||||
#
|
||||
# Default: <empty map>
|
||||
response:
|
||||
X-Powered-By: "RoadRunner"
|
||||
|
||||
# Settings for serving static content (docs: https://roadrunner.dev/docs/http-static).
|
||||
static:
|
||||
# Path to the directory with static assets.
|
||||
#
|
||||
# This option is required.
|
||||
dir: "./public"
|
||||
|
||||
# File extensions to forbid.
|
||||
#
|
||||
# Default: []
|
||||
forbid: [".htaccess", ".php"]
|
||||
|
||||
# Automatically add headers to every response.
|
||||
#
|
||||
# Default: <empty map>
|
||||
response:
|
||||
X-Powered-By: "RoadRunner"
|
||||
|
||||
# Workers pool settings.
|
||||
pool:
|
||||
debug: true
|
||||
# How many worker processes will be started. Zero (or nothing) means the number of logical CPUs.
|
||||
#
|
||||
# Default: 0
|
||||
num_workers: 4
|
||||
|
||||
# Maximal count of worker executions. Zero (or nothing) means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_jobs: 64
|
||||
|
||||
# Timeout for worker allocation. Zero means no limit.
|
||||
#
|
||||
# Default: 60s
|
||||
allocate_timeout: 10s
|
||||
|
||||
# Timeout for worker destroying before process killing. Zero means no limit.
|
||||
#
|
||||
# Default: 60s
|
||||
destroy_timeout: 10s
|
||||
|
||||
# Supervisor is used to control http workers (previous name was "limit", docs:
|
||||
# https://roadrunner.dev/docs/php-limit). "Soft" limits will not interrupt current request processing. "Hard"
|
||||
# limit on the contrary - interrupts the execution of the request.
|
||||
supervisor:
|
||||
# Maximal worker memory usage in megabytes (soft limit). Zero means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_worker_memory: 128
|
||||
|
||||
# Maximal job lifetime (hard limit). Zero means no limit.
|
||||
#
|
||||
# Default: 0s
|
||||
exec_ttl: 60s
|
||||
|
||||
# HTTP/2 settings.
|
||||
http2:
|
||||
# HTTP/2 over non-encrypted TCP connection using H2C.
|
||||
#
|
||||
# Default: false
|
||||
h2c: false
|
||||
|
||||
# Maximal concurrent streams count.
|
||||
#
|
||||
# Default: 128
|
||||
max_concurrent_streams: 128
|
||||
|
||||
## Application metrics in Prometheus format (docs: https://roadrunner.dev/docs/beep-beep-metrics). Drop this section
|
||||
## for this feature disabling.
|
||||
#metrics:
|
||||
# # Prometheus client address (path /metrics added automatically).
|
||||
# #
|
||||
# # Default: "127.0.0.1:2112"
|
||||
# address: 127.0.0.1:8081
|
||||
|
||||
# Health check endpoint (docs: https://roadrunner.dev/docs/beep-beep-health). If response code is 200 - it means at
|
||||
# least one worker ready to serve requests. 500 - there are no workers ready to service requests.
|
||||
# Drop this section for this feature disabling.
|
||||
status:
|
||||
# Host and port to listen on (eg.: `127.0.0.1:2114`). Use the following URL: http://127.0.0.1:2114/health?plugin=http
|
||||
# Multiple plugins must be separated using "&" - http://127.0.0.1:2114/health?plugin=http&plugin=rpc where "http" and
|
||||
# "rpc" are active (connected) plugins.
|
||||
#
|
||||
# This option is required.
|
||||
address: 127.0.0.1:2114
|
||||
|
||||
# Response status code if a requested plugin not ready to handle requests
|
||||
# Valid for both /health and /ready endpoints
|
||||
#
|
||||
# Default: 503
|
||||
unavailable_status_code: 503
|
||||
|
||||
# Automatically detect PHP file changes and reload connected services (docs:
|
||||
# https://roadrunner.dev/docs/beep-beep-reload). Drop this section for this feature disabling.
|
||||
reload:
|
||||
# Sync interval.
|
||||
#
|
||||
# Default: "1s"
|
||||
interval: 1s
|
||||
|
||||
# Global patterns to sync.
|
||||
#
|
||||
# Default: [".php"]
|
||||
patterns: [".php"]
|
||||
|
||||
# List of included for sync services (this is a map, where key name is a plugin name).
|
||||
#
|
||||
# Default: <empty map>
|
||||
services:
|
||||
http:
|
||||
# Directories to sync. If recursive is set to true, recursive sync will be applied only to the directories in
|
||||
# "dirs" section. Dot (.) means "current working directory".
|
||||
#
|
||||
# Default: []
|
||||
dirs: ["."]
|
||||
|
||||
# Recursive search for file patterns to add.
|
||||
#
|
||||
# Default: false
|
||||
recursive: true
|
||||
|
||||
# Ignored folders.
|
||||
#
|
||||
# Default: []
|
||||
ignore: ["vendor"]
|
||||
|
||||
# RoadRunner internal container configuration (docs: https://github.com/spiral/endure).
|
||||
endure:
|
||||
# Logging level. Possible values: "debug", "info", "warning", "error", "panic", "fatal".
|
||||
#
|
||||
# Default: "error"
|
||||
log_level: error
|
||||
app:
|
||||
debug: true
|
220
.rr.local.yaml
Normal file
220
.rr.local.yaml
Normal file
@ -0,0 +1,220 @@
|
||||
# ---------------------------------------------------------------------------------------------------
|
||||
# WARNING! This file should be used ONLY for local application development. NOT for production usage!
|
||||
# ---------------------------------------------------------------------------------------------------
|
||||
|
||||
# Hint: RR will replace any config options using reference to environment variables,
|
||||
# eg.: `option_key: ${ENVIRONMENT_VARIABLE_NAME}`.
|
||||
|
||||
# RR configuration version
|
||||
version: "2.7"
|
||||
|
||||
# Remote Procedures Calling (docs: https://roadrunner.dev/docs/beep-beep-rpc)
|
||||
# Is used for connecting to RoadRunner server from your PHP workers.
|
||||
rpc:
|
||||
# TCP address:port for listening.
|
||||
#
|
||||
# Default: "tcp://127.0.0.1:6001"
|
||||
listen: tcp://127.0.0.1:6001
|
||||
|
||||
# Application server settings (docs: https://roadrunner.dev/docs/php-worker)
|
||||
server:
|
||||
# Worker starting command, with any required arguments.
|
||||
#
|
||||
# This option is required.
|
||||
command: "php -dxdebug.start_with_request=trigger -dxdebug.mode=debug -dxdebug.client_port=9000 -dxdebug.client_host=127.0.0.1 -didekey=PHPSTORM ./vendor/bin/rr-worker start"
|
||||
env:
|
||||
- XDEBUG_SESSION: "1"
|
||||
|
||||
## Environment variables for the worker processes.
|
||||
##
|
||||
## Default: <empty map>
|
||||
#env:
|
||||
# - SOME_KEY: "SOME_VALUE"
|
||||
# - SOME_KEY2: "SOME_VALUE2"
|
||||
|
||||
# Worker relay can be: "pipes", TCP (eg.: tcp://127.0.0.1:6001), or socket (eg.: unix:///var/run/rr-relay.sock).
|
||||
#
|
||||
# Default: "pipes"
|
||||
relay: "pipes"
|
||||
|
||||
# Timeout for relay connection establishing (only for socket and TCP port relay).
|
||||
#
|
||||
# Default: 60s
|
||||
relay_timeout: 60s
|
||||
|
||||
# HTTP plugin settings.
|
||||
http:
|
||||
# Host and port to listen on (eg.: `127.0.0.1:8080`).
|
||||
#
|
||||
# This option is required.
|
||||
address: 0.0.0.0:8080
|
||||
|
||||
# HTTP access logs
|
||||
#
|
||||
# Default: false
|
||||
access_logs: true
|
||||
|
||||
# Maximal incoming request size in megabytes. Zero means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_request_size: 256
|
||||
|
||||
# Middlewares for the http plugin, order is important. Allowed values is: "headers", "gzip".
|
||||
#
|
||||
# Default value: []
|
||||
middleware: ["static", "headers", "gzip"]
|
||||
|
||||
# File uploading settings.
|
||||
uploads:
|
||||
# Directory for file uploads. Empty value means to use $TEMP based on your OS.
|
||||
#
|
||||
# Default: ""
|
||||
dir: "/tmp"
|
||||
|
||||
# Deny files with the following extensions to upload.
|
||||
#
|
||||
# Default: [".php", ".exe", ".bat"]
|
||||
forbid: [".php", ".exe", ".bat", ".sh"]
|
||||
|
||||
# Settings for "headers" middleware (docs: https://roadrunner.dev/docs/http-headers).
|
||||
headers:
|
||||
# Automatically add headers to every response.
|
||||
#
|
||||
# Default: <empty map>
|
||||
response:
|
||||
X-Powered-By: "RoadRunner"
|
||||
|
||||
# Settings for serving static content (docs: https://roadrunner.dev/docs/http-static).
|
||||
static:
|
||||
# Path to the directory with static assets.
|
||||
#
|
||||
# This option is required.
|
||||
dir: "./public"
|
||||
|
||||
# File extensions to forbid.
|
||||
#
|
||||
# Default: []
|
||||
forbid: [".htaccess", ".php"]
|
||||
|
||||
# Automatically add headers to every response.
|
||||
#
|
||||
# Default: <empty map>
|
||||
response:
|
||||
X-Powered-By: "RoadRunner"
|
||||
|
||||
# Workers pool settings.
|
||||
pool:
|
||||
debug: true
|
||||
# How many worker processes will be started. Zero (or nothing) means the number of logical CPUs.
|
||||
#
|
||||
# Default: 0
|
||||
num_workers: 4
|
||||
|
||||
# Maximal count of worker executions. Zero (or nothing) means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_jobs: 64
|
||||
|
||||
# Timeout for worker allocation. Zero means no limit.
|
||||
#
|
||||
# Default: 60s
|
||||
allocate_timeout: 10s
|
||||
|
||||
# Timeout for worker destroying before process killing. Zero means no limit.
|
||||
#
|
||||
# Default: 60s
|
||||
destroy_timeout: 10s
|
||||
|
||||
# Supervisor is used to control http workers (previous name was "limit", docs:
|
||||
# https://roadrunner.dev/docs/php-limit). "Soft" limits will not interrupt current request processing. "Hard"
|
||||
# limit on the contrary - interrupts the execution of the request.
|
||||
supervisor:
|
||||
# Maximal worker memory usage in megabytes (soft limit). Zero means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_worker_memory: 128
|
||||
|
||||
# Maximal job lifetime (hard limit). Zero means no limit.
|
||||
#
|
||||
# Default: 0s
|
||||
exec_ttl: 60s
|
||||
|
||||
# HTTP/2 settings.
|
||||
http2:
|
||||
# HTTP/2 over non-encrypted TCP connection using H2C.
|
||||
#
|
||||
# Default: false
|
||||
h2c: false
|
||||
|
||||
# Maximal concurrent streams count.
|
||||
#
|
||||
# Default: 128
|
||||
max_concurrent_streams: 128
|
||||
|
||||
## Application metrics in Prometheus format (docs: https://roadrunner.dev/docs/beep-beep-metrics). Drop this section
|
||||
## for this feature disabling.
|
||||
#metrics:
|
||||
# # Prometheus client address (path /metrics added automatically).
|
||||
# #
|
||||
# # Default: "127.0.0.1:2112"
|
||||
# address: 127.0.0.1:8081
|
||||
|
||||
# Health check endpoint (docs: https://roadrunner.dev/docs/beep-beep-health). If response code is 200 - it means at
|
||||
# least one worker ready to serve requests. 500 - there are no workers ready to service requests.
|
||||
# Drop this section for this feature disabling.
|
||||
status:
|
||||
# Host and port to listen on (eg.: `127.0.0.1:2114`). Use the following URL: http://127.0.0.1:2114/health?plugin=http
|
||||
# Multiple plugins must be separated using "&" - http://127.0.0.1:2114/health?plugin=http&plugin=rpc where "http" and
|
||||
# "rpc" are active (connected) plugins.
|
||||
#
|
||||
# This option is required.
|
||||
address: 127.0.0.1:2114
|
||||
|
||||
# Response status code if a requested plugin not ready to handle requests
|
||||
# Valid for both /health and /ready endpoints
|
||||
#
|
||||
# Default: 503
|
||||
unavailable_status_code: 503
|
||||
|
||||
# Automatically detect PHP file changes and reload connected services (docs:
|
||||
# https://roadrunner.dev/docs/beep-beep-reload). Drop this section for this feature disabling.
|
||||
reload:
|
||||
# Sync interval.
|
||||
#
|
||||
# Default: "1s"
|
||||
interval: 1s
|
||||
|
||||
# Global patterns to sync.
|
||||
#
|
||||
# Default: [".php"]
|
||||
patterns: [".php"]
|
||||
|
||||
# List of included for sync services (this is a map, where key name is a plugin name).
|
||||
#
|
||||
# Default: <empty map>
|
||||
services:
|
||||
http:
|
||||
# Directories to sync. If recursive is set to true, recursive sync will be applied only to the directories in
|
||||
# "dirs" section. Dot (.) means "current working directory".
|
||||
#
|
||||
# Default: []
|
||||
dirs: ["."]
|
||||
|
||||
# Recursive search for file patterns to add.
|
||||
#
|
||||
# Default: false
|
||||
recursive: true
|
||||
|
||||
# Ignored folders.
|
||||
#
|
||||
# Default: []
|
||||
ignore: ["vendor"]
|
||||
|
||||
# RoadRunner internal container configuration (docs: https://github.com/spiral/endure).
|
||||
endure:
|
||||
# Logging level. Possible values: "debug", "info", "warning", "error", "panic", "fatal".
|
||||
#
|
||||
# Default: "error"
|
||||
log_level: error
|
||||
app:
|
||||
debug: true
|
214
.rr.yaml
Normal file
214
.rr.yaml
Normal file
@ -0,0 +1,214 @@
|
||||
# Production usage guide: https://roadrunner.dev/docs/beep-beep-production
|
||||
|
||||
# Hint: RR will replace any config options using reference to environment variables,
|
||||
# eg.: `option_key: ${ENVIRONMENT_VARIABLE_NAME}`.
|
||||
# Please note that this config is used within the docker container.
|
||||
|
||||
# RR configuration version
|
||||
version: "2.7"
|
||||
|
||||
# Remote Procedures Calling (docs: https://roadrunner.dev/docs/beep-beep-rpc)
|
||||
# Is used for connecting to RoadRunner server from your PHP workers.
|
||||
rpc:
|
||||
# TCP address:port for listening.
|
||||
#
|
||||
# Default: "tcp://127.0.0.1:6001"
|
||||
listen: tcp://127.0.0.1:6001
|
||||
|
||||
# Application server settings (docs: https://roadrunner.dev/docs/php-worker)
|
||||
server:
|
||||
# Worker starting command, with any required arguments.
|
||||
#
|
||||
# This option is required.
|
||||
command: "php ./vendor/bin/rr-worker start --relay-dsn unix:///var/run/rr/rr-relay.sock"
|
||||
|
||||
## Environment variables for the worker processes.
|
||||
##
|
||||
## Default: <empty map>
|
||||
#env:
|
||||
# - SOME_KEY: "SOME_VALUE"
|
||||
# - SOME_KEY2: "SOME_VALUE2"
|
||||
|
||||
# Worker relay can be: "pipes", TCP (eg.: tcp://127.0.0.1:6001), or socket (eg.: unix:///var/run/rr-relay.sock).
|
||||
#
|
||||
# Default: "pipes"
|
||||
relay: "unix:///var/run/rr/rr-relay.sock"
|
||||
|
||||
# Timeout for relay connection establishing (only for socket and TCP port relay).
|
||||
#
|
||||
# Default: 60s
|
||||
relay_timeout: 60s
|
||||
|
||||
# Logging settings (docs: https://roadrunner.dev/docs/beep-beep-logging)
|
||||
logs:
|
||||
# Logging mode can be "development" or "production". Do not forget to change this value for production environment.
|
||||
#
|
||||
# Development mode (which makes DPanicLevel logs panic), uses a console encoder, writes to standard error, and
|
||||
# disables sampling. Stacktraces are automatically included on logs of WarnLevel and above.
|
||||
#
|
||||
# Default: "development"
|
||||
mode: production
|
||||
|
||||
# Logging level can be "panic", "error", "warning", "info", "debug".
|
||||
#
|
||||
# Default: "debug"
|
||||
level: info
|
||||
|
||||
# Encoding format can be "console" or "json" (last is preferred for production usage).
|
||||
#
|
||||
# Default: "console"
|
||||
encoding: json
|
||||
|
||||
# we want to use docker's log drivers, so push logs to stdout
|
||||
output: stdout
|
||||
# we to use docker's log drivers, so push error logs to stdout
|
||||
# this way it is possible for example to pipe logs to journald or to AWS Cloudwatch
|
||||
err_output: stdout
|
||||
|
||||
# HTTP plugin settings.
|
||||
http:
|
||||
# Host and port to listen on (eg.: `127.0.0.1:8080`).
|
||||
#
|
||||
# This option is required.
|
||||
address: 0.0.0.0:8080
|
||||
|
||||
# HTTP access logs
|
||||
#
|
||||
# Default: false
|
||||
access_logs: true
|
||||
|
||||
# Maximal incoming request size in megabytes. Zero means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_request_size: 256
|
||||
|
||||
# Middlewares for the http plugin, order is important. Allowed values is: "headers", "gzip".
|
||||
#
|
||||
# Default value: []
|
||||
middleware: ["static", "headers", "gzip"]
|
||||
|
||||
# File uploading settings.
|
||||
uploads:
|
||||
# Directory for file uploads. Empty value means to use $TEMP based on your OS.
|
||||
#
|
||||
# Default: ""
|
||||
dir: "/tmp"
|
||||
|
||||
# Deny files with the following extensions to upload.
|
||||
#
|
||||
# Default: [".php", ".exe", ".bat"]
|
||||
forbid: [".php", ".exe", ".bat", ".sh"]
|
||||
|
||||
# Settings for "headers" middleware (docs: https://roadrunner.dev/docs/http-headers).
|
||||
headers:
|
||||
# Automatically add headers to every response.
|
||||
#
|
||||
# Default: <empty map>
|
||||
response:
|
||||
X-Powered-By: "RoadRunner"
|
||||
|
||||
# Settings for serving static content (docs: https://roadrunner.dev/docs/http-static).
|
||||
static:
|
||||
# Path to the directory with static assets.
|
||||
#
|
||||
# This option is required.
|
||||
dir: "./public"
|
||||
|
||||
# File extensions to forbid.
|
||||
#
|
||||
# Default: []
|
||||
forbid: [".htaccess", ".php"]
|
||||
|
||||
# Automatically add headers to every response.
|
||||
#
|
||||
# Default: <empty map>
|
||||
response:
|
||||
X-Powered-By: "RoadRunner"
|
||||
|
||||
# Workers pool settings.
|
||||
pool:
|
||||
# How many worker processes will be started. Zero (or nothing) means the number of logical CPUs.
|
||||
#
|
||||
# Default: 0
|
||||
num_workers: 0
|
||||
|
||||
# Maximal count of worker executions. Zero (or nothing) means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_jobs: 64
|
||||
|
||||
# Timeout for worker allocation. Zero means no limit.
|
||||
#
|
||||
# Default: 60s
|
||||
allocate_timeout: 10s
|
||||
|
||||
# Timeout for worker destroying before process killing. Zero means no limit.
|
||||
#
|
||||
# Default: 60s
|
||||
destroy_timeout: 10s
|
||||
|
||||
# Supervisor is used to control http workers (previous name was "limit", docs:
|
||||
# https://roadrunner.dev/docs/php-limit). "Soft" limits will not interrupt current request processing. "Hard"
|
||||
# limit on the contrary - interrupts the execution of the request.
|
||||
supervisor:
|
||||
# Maximal worker memory usage in megabytes (soft limit). Zero means no limit.
|
||||
#
|
||||
# Default: 0
|
||||
max_worker_memory: 128
|
||||
|
||||
# Maximal job lifetime (hard limit). Zero means no limit.
|
||||
#
|
||||
# Default: 0s
|
||||
exec_ttl: 60s
|
||||
|
||||
# HTTP/2 settings.
|
||||
http2:
|
||||
# HTTP/2 over non-encrypted TCP connection using H2C.
|
||||
#
|
||||
# Default: false
|
||||
h2c: false
|
||||
|
||||
# Maximal concurrent streams count.
|
||||
#
|
||||
# Default: 128
|
||||
max_concurrent_streams: 128
|
||||
|
||||
## Application metrics in Prometheus format (docs: https://roadrunner.dev/docs/beep-beep-metrics). Drop this section
|
||||
## for this feature disabling.
|
||||
#metrics:
|
||||
# # Prometheus client address (path /metrics added automatically).
|
||||
# #
|
||||
# # Default: "127.0.0.1:2112"
|
||||
# address: 127.0.0.1:8081
|
||||
|
||||
# Health check endpoint (docs: https://roadrunner.dev/docs/beep-beep-health). If response code is 200 - it means at
|
||||
# least one worker ready to serve requests. 500 - there are no workers ready to service requests.
|
||||
# Drop this section for this feature disabling.
|
||||
status:
|
||||
# Host and port to listen on (eg.: `127.0.0.1:2114`). Use the following URL: http://127.0.0.1:2114/health?plugin=http
|
||||
# Multiple plugins must be separated using "&" - http://127.0.0.1:2114/health?plugin=http&plugin=rpc where "http" and
|
||||
# "rpc" are active (connected) plugins.
|
||||
#
|
||||
# This option is required.
|
||||
address: 127.0.0.1:2114
|
||||
|
||||
# Response status code if a requested plugin not ready to handle requests
|
||||
# Valid for both /health and /ready endpoints
|
||||
#
|
||||
# Default: 503
|
||||
unavailable_status_code: 503
|
||||
|
||||
service:
|
||||
laravel_queue_worker_1:
|
||||
command: "php /app/artisan queue:work --queue=high,default"
|
||||
process_num: 1
|
||||
restart_sec: 5
|
||||
supercronic:
|
||||
command: "supercronic /etc/supercronic/laravel"
|
||||
|
||||
# RoadRunner internal container configuration (docs: https://github.com/spiral/endure).
|
||||
endure:
|
||||
# Logging level. Possible values: "debug", "info", "warning", "error", "panic", "fatal".
|
||||
#
|
||||
# Default: "error"
|
||||
log_level: error
|
63
Dockerfile
Normal file
63
Dockerfile
Normal file
@ -0,0 +1,63 @@
|
||||
ARG BASE_IMAGE_VERSION="latest"
|
||||
FROM jikanme/jikan-rest-php:${BASE_IMAGE_VERSION}
|
||||
ARG GITHUB_PERSONAL_TOKEN
|
||||
LABEL org.opencontainers.image.source=https://github.com/jikan-me/jikan-rest
|
||||
RUN set -ex \
|
||||
&& apt-get update && apt-get install -y --no-install-recommends \
|
||||
openssl \
|
||||
git \
|
||||
dos2unix \
|
||||
unzip \
|
||||
wget \
|
||||
# install supercronic (for laravel task scheduling), project page: <https://github.com/aptible/supercronic>
|
||||
&& wget -q "https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64" \
|
||||
-O /usr/bin/supercronic \
|
||||
&& chmod +x /usr/bin/supercronic \
|
||||
&& mkdir /etc/supercronic \
|
||||
&& echo '*/1 * * * * php /app/artisan schedule:run' > /etc/supercronic/laravel \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
# enable opcache for CLI and JIT, docs: <https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.jit>
|
||||
&& echo -e "\nopcache.enable=1\nopcache.enable_cli=1\nopcache.jit_buffer_size=32M\nopcache.jit=1235\n" >> \
|
||||
${PHP_INI_DIR}/conf.d/docker-php-ext-opcache.ini \
|
||||
# show installed modules
|
||||
&& php -m \
|
||||
# create unpriviliged user
|
||||
&& adduser --disabled-password --shell "/sbin/nologin" --home "/nonexistent" --no-create-home --uid "10001" --gecos "" "jikanapi" \
|
||||
&& mkdir /app /var/run/rr \
|
||||
&& chown -R jikanapi:jikanapi /app /var/run/rr /etc/supercronic/laravel \
|
||||
&& chmod -R 777 /var/run/rr
|
||||
|
||||
USER jikanapi:jikanapi
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# copy composer (json|lock) files for dependencies layer caching
|
||||
COPY --chown=jikanapi:jikanapi ./composer.* /app/
|
||||
|
||||
# check if GITHUB_PERSONAL_TOKEN is set and configure it for composer
|
||||
# it is recommended to set this for the build, otherwise the build might fail because of github's rate limits
|
||||
RUN if [ -z "$GITHUB_PERSONAL_TOKEN" ]; then echo "** GITHUB_PERSONAL_TOKEN is not set. This build may fail due to github rate limits."; \
|
||||
else composer config github-oauth.github.com "$GITHUB_PERSONAL_TOKEN"; fi
|
||||
|
||||
# install composer dependencies (autoloader MUST be generated later!)
|
||||
RUN composer install -n --no-dev --no-cache --no-ansi --no-autoloader --no-scripts --prefer-dist
|
||||
|
||||
# copy application sources into image (completely)
|
||||
COPY --chown=jikanapi:jikanapi . /app/
|
||||
|
||||
RUN set -ex \
|
||||
&& composer update jikan-me/jikan \
|
||||
&& composer dump-autoload -n --optimize \
|
||||
&& chmod -R 777 ${COMPOSER_HOME}/cache \
|
||||
&& chmod -R a+w storage/ \
|
||||
&& chown -R jikanapi:jikanapi /app \
|
||||
&& chmod +x docker-entrypoint.php \
|
||||
&& chmod +x docker-entrypoint.sh
|
||||
|
||||
EXPOSE 8080
|
||||
EXPOSE 2114
|
||||
|
||||
HEALTHCHECK CMD curl --fail http://localhost:2114/health?plugin=http || exit 1
|
||||
|
||||
# unset default image entrypoint.
|
||||
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
@ -25,7 +25,12 @@ Please read the [manual installation guide](https://github.com/jikan-me/jikan-re
|
||||
For any additional help, join our [Discord server](http://discord.jikan.moe/).
|
||||
|
||||
### 🐳 Docker Installation
|
||||
If you don't want to install it manually, you can use the [docker image](https://github.com/jikan-me/jikan-docker)
|
||||
We distribute the app as a container image so you can just run it:
|
||||
```bash
|
||||
docker run -d --name=jikan-rest -p 8080:8080 -v ./.env:/app/.env jikanme/jikan-rest:latest
|
||||
```
|
||||
|
||||
For more information please refer to our [container usage guide](container_usage.md).
|
||||
|
||||
## Public REST API
|
||||
If you don't want to host your instance, there's a public API available.
|
||||
|
@ -89,24 +89,26 @@ class Anime extends JikanApiSearchableModel
|
||||
|
||||
public function getBroadcastAttribute()
|
||||
{
|
||||
$broadcastStr = $this->attributes['broadcast'];
|
||||
if (array_key_exists("broadcast", $this->attributes)) {
|
||||
$broadcastStr = $this->attributes['broadcast'];
|
||||
|
||||
if (!preg_match('~(.*) at (.*) \(~', $broadcastStr, $matches)) {
|
||||
return [
|
||||
'day' => null,
|
||||
'time' => null,
|
||||
'timezone' => null,
|
||||
'string' => $broadcastStr
|
||||
];
|
||||
}
|
||||
if (!preg_match('~(.*) at (.*) \(~', $broadcastStr, $matches)) {
|
||||
return [
|
||||
'day' => null,
|
||||
'time' => null,
|
||||
'timezone' => null,
|
||||
'string' => $broadcastStr
|
||||
];
|
||||
}
|
||||
|
||||
if (preg_match('~(.*) at (.*) \(~', $broadcastStr, $matches)) {
|
||||
return [
|
||||
'day' => $matches[1],
|
||||
'time' => $matches[2],
|
||||
'timezone' => 'Asia/Tokyo',
|
||||
'string' => $broadcastStr
|
||||
];
|
||||
if (preg_match('~(.*) at (.*) \(~', $broadcastStr, $matches)) {
|
||||
return [
|
||||
'day' => $matches[1],
|
||||
'time' => $matches[2],
|
||||
'timezone' => 'Asia/Tokyo',
|
||||
'string' => $broadcastStr
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
|
@ -52,7 +52,7 @@ class GithubReport
|
||||
/**
|
||||
* @var string|bool
|
||||
*/
|
||||
private string|bool $redisRunning;
|
||||
private string|bool $redisRunning = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -94,7 +94,12 @@ class GithubReport
|
||||
|
||||
$report->instanceType = 'UNKNOWN';
|
||||
if (env('APP_ENV') !== 'testing') {
|
||||
$report->instanceType = $_SERVER['SERVER_NAME'] === 'api.jikan.moe' ? 'OFFICIAL' : 'HOSTED';
|
||||
if (array_key_exists('SERVER_NAME', $_SERVER)) {
|
||||
$report->instanceType = $_SERVER['SERVER_NAME'] === 'api.jikan.moe' ? 'OFFICIAL' : 'HOSTED';
|
||||
}
|
||||
else {
|
||||
$report->instanceType = 'HOSTED-RR';
|
||||
}
|
||||
}
|
||||
|
||||
return $report;
|
||||
|
@ -45,7 +45,7 @@ class Insights
|
||||
->insert([
|
||||
'timestamp' => time(),
|
||||
'url' => $request->getRequestUri(),
|
||||
'type' =>
|
||||
'type' => ""
|
||||
]);
|
||||
}
|
||||
|
||||
|
29
app/Listeners/PsrWorkerErrorListener.php
Normal file
29
app/Listeners/PsrWorkerErrorListener.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use pushrbx\LumenRoadRunner\Events\LoopErrorOccurredEvent;
|
||||
|
||||
class PsrWorkerErrorListener
|
||||
{
|
||||
private \App\Exceptions\Handler $exceptionHandler;
|
||||
private Logger $logger;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->exceptionHandler = new \App\Exceptions\Handler;
|
||||
$this->logger = new Logger('psr-worker');
|
||||
$this->logger->pushHandler(new StreamHandler(storage_path().'/logs/psr-worker.log'), env('APP_DEBUG') ? Logger::DEBUG : Logger::WARNING);
|
||||
}
|
||||
|
||||
public function handle(LoopErrorOccurredEvent $event): void
|
||||
{
|
||||
try {
|
||||
$this->exceptionHandler->report($event->exception());
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ use App\Services\TypeSenseScoutSearchService;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Collection;
|
||||
use Laravel\Scout\Builder as ScoutBuilder;
|
||||
use Typesense\LaravelTypesense\Typesense;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@ -161,4 +162,28 @@ class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
return $app["config"]->get("scout.driver");
|
||||
}
|
||||
|
||||
public static function servicesToWarm(): array
|
||||
{
|
||||
$services = [
|
||||
ScoutSearchService::class,
|
||||
AnimeSearchQueryBuilder::class,
|
||||
MangaSearchQueryBuilder::class,
|
||||
ClubSearchQueryBuilder::class,
|
||||
CharacterSearchQueryBuilder::class,
|
||||
PeopleSearchQueryBuilder::class,
|
||||
TopAnimeQueryBuilder::class,
|
||||
TopMangaQueryBuilder::class
|
||||
];
|
||||
|
||||
if (env("SCOUT_DRIVER") === "typesense") {
|
||||
$services[] = Typesense::class;
|
||||
}
|
||||
|
||||
if (env("SCOUT_DRIVER") === "Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine") {
|
||||
$services[] = \Elastic\Elasticsearch\Client::class;
|
||||
}
|
||||
|
||||
return $services;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
|
||||
use pushrbx\LumenRoadRunner\Events\LoopErrorOccurredEvent;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
@ -12,8 +13,8 @@ class EventServiceProvider extends ServiceProvider
|
||||
* @var array
|
||||
*/
|
||||
protected $listen = [
|
||||
'App\Events\SomeEvent' => [
|
||||
'App\Listeners\EventListener',
|
||||
],
|
||||
LoopErrorOccurredEvent::class => [
|
||||
\App\Listeners\PsrWorkerErrorListener::class
|
||||
]
|
||||
];
|
||||
}
|
||||
|
@ -112,10 +112,13 @@ $app->configure('database');
|
||||
$app->configure('queue');
|
||||
$app->configure('controller-to-table-mapping');
|
||||
$app->configure('controller');
|
||||
$app->configure('roadrunner');
|
||||
|
||||
$app->register(\pushrbx\LumenRoadRunner\ServiceProvider::class);
|
||||
$app->register(\SwaggerLume\ServiceProvider::class);
|
||||
$app->register(Flipbox\LumenGenerator\LumenGeneratorServiceProvider::class);
|
||||
$app->register(\App\Providers\SourceHeartbeatProvider::class);
|
||||
$app->register(\App\Providers\EventServiceProvider::class);
|
||||
$app->register(Illuminate\Database\Eloquent\LegacyFactoryServiceProvider::class);
|
||||
$app->register(\App\Providers\AppServiceProvider::class);
|
||||
|
||||
@ -153,7 +156,7 @@ $app->register(Laravel\Scout\ScoutServiceProvider::class);
|
||||
// we support TypeSense and ElasticSearch as search indexes.
|
||||
if (env("SCOUT_DRIVER") === "typesense") {
|
||||
// in this case the TYPESENSE_HOST env var should be set too
|
||||
$app->register(Typesense\LaravelTypesense\TypesenseServiceProvider::class);
|
||||
$app->register(\Typesense\LaravelTypesense\TypesenseServiceProvider::class);
|
||||
}
|
||||
if (env("SCOUT_DRIVER") === "Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine") {
|
||||
// in this case the ELASTICSEARCH_HOST env var should be set too
|
||||
|
@ -4,6 +4,12 @@
|
||||
"keywords": ["framework", "laravel", "lumen"],
|
||||
"license": "MIT",
|
||||
"type": "project",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pushrbx/lumen-roadrunner"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"ext-json": "*",
|
||||
@ -22,8 +28,10 @@
|
||||
"laravel/scout": "^9.4",
|
||||
"league/flysystem": "^3.0",
|
||||
"matchish/laravel-scout-elasticsearch": "^6.0",
|
||||
"mirazmac/dotenvwriter": "^0.1.0",
|
||||
"ocramius/package-versions": "^2.5",
|
||||
"predis/predis": "^1.1",
|
||||
"pushrbx/lumen-roadrunner": "dev-master",
|
||||
"sentry/sentry-laravel": "^2.8",
|
||||
"symfony/yaml": "^4.1",
|
||||
"typesense/laravel-scout-typesense-driver": "^5.0",
|
||||
|
124
config/roadrunner.php
Normal file
124
config/roadrunner.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
use pushrbx\LumenRoadRunner\Events;
|
||||
use pushrbx\LumenRoadRunner\Defaults;
|
||||
use pushrbx\LumenRoadRunner\Listeners;
|
||||
use Spiral\RoadRunner\Environment\Mode;
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Force HTTPS Schema Usage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set this value to `true` if your application uses HTTPS (required for
|
||||
| correct links generation, for example).
|
||||
|
|
||||
*/
|
||||
|
||||
'force_https' => (bool)env('APP_FORCE_HTTPS', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Event Listeners
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Worker provided by this package allows to interacts with request
|
||||
| processing loop using application events.
|
||||
|
|
||||
| Feel free to add your own event listeners.
|
||||
|
|
||||
*/
|
||||
|
||||
'listeners' => [
|
||||
Events\BeforeLoopStartedEvent::class => [
|
||||
...Defaults::beforeLoopStarted(),
|
||||
],
|
||||
|
||||
Events\BeforeLoopIterationEvent::class => [
|
||||
...Defaults::beforeLoopIteration(),
|
||||
],
|
||||
|
||||
Events\BeforeRequestHandlingEvent::class => [
|
||||
...Defaults::beforeRequestHandling(),
|
||||
Listeners\InjectStatsIntoRequestListener::class
|
||||
],
|
||||
|
||||
Events\AfterRequestHandlingEvent::class => [
|
||||
...Defaults::afterRequestHandling(),
|
||||
],
|
||||
|
||||
Events\AfterLoopIterationEvent::class => [
|
||||
...Defaults::afterLoopIteration(),
|
||||
Listeners\RunGarbageCollectorListener::class, // keep the memory usage low
|
||||
// Listeners\CleanupUploadedFilesListener::class, // remove temporary files
|
||||
],
|
||||
|
||||
Events\AfterLoopStoppedEvent::class => [
|
||||
...Defaults::afterLoopStopped(),
|
||||
],
|
||||
|
||||
Events\LoopErrorOccurredEvent::class => [
|
||||
...Defaults::loopErrorOccurred(),
|
||||
Listeners\SendExceptionToStderrListener::class,
|
||||
Listeners\StopWorkerListener::class,
|
||||
\App\Listeners\PsrWorkerErrorListener::class,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Containers Pre Resolving / Clearing
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The bindings listed below will be resolved before the events loop
|
||||
| starting. Clearing a binding will force the container to resolve that
|
||||
| binding again when asked.
|
||||
|
|
||||
| Feel free to add your own bindings here.
|
||||
|
|
||||
*/
|
||||
|
||||
'warm' => [
|
||||
...Defaults::servicesToWarm(),
|
||||
...\App\Providers\AppServiceProvider::servicesToWarm()
|
||||
],
|
||||
|
||||
'clear' => [
|
||||
...Defaults::servicesToClear(),
|
||||
'auth', // is not required for Laravel >= v8.35
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Reset Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Providers that will be registered on every request.
|
||||
|
|
||||
| Feel free to add your service-providers here.
|
||||
|
|
||||
*/
|
||||
|
||||
'reset_providers' => [
|
||||
...Defaults::providersToReset(),
|
||||
Illuminate\Auth\AuthServiceProvider::class, // is not required for Laravel >= v8.35
|
||||
Illuminate\Pagination\PaginationServiceProvider::class, // is not required for Laravel >= v8.35
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Worker Classes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you can override the worker class for processing different kinds of
|
||||
| jobs, that received from the RoadRunner daemon. The key is a worker mode.
|
||||
|
|
||||
*/
|
||||
|
||||
'workers' => [
|
||||
Mode::MODE_HTTP => \pushrbx\LumenRoadRunner\Worker::class,
|
||||
// Mode::MODE_JOBS => ...,
|
||||
// Mode::MODE_TEMPORAL => ...,
|
||||
],
|
||||
];
|
71
container_usage.md
Normal file
71
container_usage.md
Normal file
@ -0,0 +1,71 @@
|
||||
# 🐳 Running Jikan API in a container
|
||||
|
||||
```bash
|
||||
docker run -d --name=jikan-rest -p 8080:8080 -v ./.env:/app/.env jikanme/jikan-rest:latest
|
||||
```
|
||||
- Container listens on port `8080` for http requests
|
||||
- By mounting your .env file on the container via `-v ./.env:/app/.env` command line option for `docker run` you can configure Jikan API.
|
||||
|
||||
> **Important**: You need to either mount a `.env` file on the container or specify the configuration through environment variables to make Jikan API work in the container. Jikan API needs a MongoDB and optionally a search engine. In high load environments additionally a `redis` server is required too. The configuration should point to the correct address of these services.
|
||||
|
||||
> **Tip**: If you run the container on a non-default network, you can use the container names in the configuration to specify the address of services like MongoDB and TypeSense/ElasticSearch. However this is not a concern if you use `docker-compose`.
|
||||
|
||||
There is also a `Dockerfile` in the repo which you can use to build the container image and startup the app in a container:
|
||||
```bash
|
||||
docker build -t jikan-rest:nightly .
|
||||
docker run -d --name=jikan-rest -p 8080:8080 -v ./.env:/app/.env jikan-rest:nightly
|
||||
```
|
||||
|
||||
### Docker compose usage
|
||||
|
||||
```
|
||||
docker-compose up
|
||||
```
|
||||
Docker compose will use the `.env` file from the folder where you execute it from to load configurations for the services. If you don't have a `.env` file yet in the folder, copy the `.env.dist` file, and set the passwords.
|
||||
|
||||
> **Please note**: The syntax rules of docker compose for `.env` applies here: https://docs.docker.com/compose/env-file/#syntax-rules
|
||||
|
||||
#### Note for Podman
|
||||
|
||||
If you build the container image yourself with podman, the resulting image format will be OCI by default.
|
||||
To make the health checks work in that situation you need to run the container the following way:
|
||||
```bash
|
||||
podman run -d --name=jikan-rest -p 8080:8080 -v ./.env:/app/.env --health-start-period=5s --health-cmd="curl --fail http://localhost:2114/health?plugin=http || exit 1" jikan-rest:nightly
|
||||
```
|
||||
|
||||
#### Configuration of the container
|
||||
|
||||
You can change the settings of Jikan through setting environment variables via the `-e` command line argument option for the `docker run` command.
|
||||
These environment variables are the same as the options found in the `.env` file. We also provide a sample file called `.env.dist`.
|
||||
Additionally, you can use the `--env-file` option of `docker run` to specify configuration for Jikan, in which case you put all the configuration in the env file.
|
||||
```bash
|
||||
docker run -d --name=jikan-rest -p 8080:8080 --env-file ./env.list jikanme/jikan-rest:latest
|
||||
```
|
||||
The env-file should contain env var value pairs line by line.
|
||||
```
|
||||
VAR1=value1
|
||||
VAR2=value2
|
||||
```
|
||||
There are additional configuration options:
|
||||
|
||||
| Name | Description |
|
||||
|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| RR_MAX_WORKER_MEMORY | (Number) Configures the available memory in megabytes for the php scripts |
|
||||
| RR_MAX_REQUEST_SIZE_MB | (Number) Configures the max allowed request body size in megabytes |
|
||||
| JIKAN_QUEUE_WORKER_PROCESS_NUM | (Number) Configures the number of running queue worker processes. (You want to increase this if you experience huge load) |
|
||||
| JIKAN_ENABLE_PERIODICAL_FULL_INDEXER | (Bool) Configures whether to run the anime/manga indexer every week, which would crawl all anime/manga at first then it would just grab the latest anime/manga entries from MAL. Defaults to false. |
|
||||
|
||||
You can read more about additional configuration options on the [Configuration Wiki page](https://github.com/jikan-me/jikan-rest/wiki/Configuration).
|
||||
|
||||
## Some facts about the container image
|
||||
|
||||
- Jikan uses RoadRunner as an application server within the container.
|
||||
- Both `wget` and `curl` exists in the container image.
|
||||
- The script in `docker-entrypoint.php` sets safe defaults. Because of this by default the app won't behave the same way as the publicly available version of the app at [https://api.jikan.moe/v4](https://api.jikan.moe/v4). The default settings:
|
||||
- No redis caching
|
||||
- No search index usage (inaccurate search results)
|
||||
- Via Roadrunner multiple processes are running in the container, and their logs are aggregated and forwarded to `stdout`.
|
||||
- These processes are:
|
||||
- the php processes ingesting the http requests
|
||||
- [Supercronic](https://github.com/aptible/supercronic), which runs cron jobs.
|
||||
- Queue workers for populating the search index and other background jobs.
|
93
docker-compose.yml
Normal file
93
docker-compose.yml
Normal file
@ -0,0 +1,93 @@
|
||||
# For now this is just for local development. This is not production ready.
|
||||
version: '3.8'
|
||||
volumes:
|
||||
mongo-data: {}
|
||||
redis-data: {}
|
||||
tmp-data: {}
|
||||
typesense-data: {}
|
||||
|
||||
services:
|
||||
jikan_rest: &jikan_rest
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
user: "${APP_UID:-10001}:${APP_GID:-10001}"
|
||||
environment:
|
||||
PS1: '\[\033[1;32m\]\[\033[1;36m\][\u@\h] \[\033[1;34m\]\w\[\033[0;35m\] \[\033[1;36m\]# \[\033[0m\]'
|
||||
HOME: /tmp
|
||||
APP_DEBUG: 'true'
|
||||
APP_ENV: local
|
||||
REDIS_HOST: redis
|
||||
REDIS_PASSWORD: "${REDIS_PASSWORD:-null}"
|
||||
DB_CONNECTION: mongodb
|
||||
DB_HOST: mongodb
|
||||
DB_DATABASE: jikan
|
||||
DB_PORT: 27017
|
||||
DB_ADMIN: jikan
|
||||
DB_USERNAME: "${DB_USERNAME}"
|
||||
DB_PASSWORD: "${DB_PASSWORD}"
|
||||
volumes:
|
||||
- /etc/passwd:/etc/passwd:ro
|
||||
- /etc/group:/etc/group:ro
|
||||
- tmp-data:/tmp:rw
|
||||
- .:/app:rw
|
||||
depends_on:
|
||||
mongodb: {condition: service_healthy}
|
||||
redis: {condition: service_healthy}
|
||||
typesense: {condition: service_healthy}
|
||||
|
||||
web:
|
||||
<<: *jikan_rest
|
||||
ports:
|
||||
- '8080:8080/tcp'
|
||||
healthcheck:
|
||||
test: [ 'CMD-SHELL', 'wget --spider -q "http://127.0.0.1:2114/health?plugin=http"' ]
|
||||
interval: 2s
|
||||
timeout: 2s
|
||||
|
||||
cron:
|
||||
<<: *jikan_rest
|
||||
command: supercronic /etc/supercronic/laravel # it runs artisan schedule:run
|
||||
|
||||
mongodb:
|
||||
image: mongo:focal
|
||||
volumes:
|
||||
- mongo-data:/data/db
|
||||
ports:
|
||||
- '27017/tcp'
|
||||
command: --wiredTigerCacheSizeGB 1
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: "${DB_USERNAME:-root}"
|
||||
MONGO_INITDB_ROOT_PASSWORD: "${DB_PASSWORD}"
|
||||
healthcheck:
|
||||
test: echo 'db.runCommand("ping").ok' | mongo mongodb://localhost:27017 --quiet
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}"
|
||||
volumes:
|
||||
- redis-data:/data:rw
|
||||
ports:
|
||||
- '6379/tcp'
|
||||
healthcheck:
|
||||
test: [ 'CMD', 'redis-cli', 'ping' ]
|
||||
interval: 500ms
|
||||
timeout: 1s
|
||||
|
||||
typesense:
|
||||
image: typesense/typesense:0.23.1
|
||||
entrypoint: /bin/sh
|
||||
command:
|
||||
- -c
|
||||
- /opt/typesense-server --data-dir /data --api-key "$${TYPESENSE_API_KEY:?TYPESENSE_API_KEY variable is not set}"
|
||||
restart: no
|
||||
volumes:
|
||||
- typesense-data:/data
|
||||
ports:
|
||||
- "8108/tcp"
|
56
docker-entrypoint.php
Executable file
56
docker-entrypoint.php
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
require_once __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$safe_defaults = [
|
||||
// mongodb regex search by default
|
||||
"SCOUT_DRIVER" => "null",
|
||||
"SCOUT_QUEUE" => false,
|
||||
"THROTTLE" => false,
|
||||
"QUEUE_CONNECTION" => "database",
|
||||
"DB_CACHING" => true,
|
||||
"DB_HOST" => "localhost",
|
||||
"DB_PORT" => 27017,
|
||||
"DB_DATABASE" => "jikan",
|
||||
"DB_USERNAME" => "",
|
||||
"DB_PASSWORD" => ""
|
||||
];
|
||||
|
||||
if (!file_exists(".env")) {
|
||||
copy(".env.dist", ".env");
|
||||
$writer = new \MirazMac\DotEnv\Writer(__DIR__ . '/' . '.env');
|
||||
|
||||
foreach ($safe_defaults as $env_var_name => $env_var_default) {
|
||||
$writer->set("SCOUT_DRIVER", env($env_var_name, $env_var_default));
|
||||
}
|
||||
$writer->write();
|
||||
}
|
||||
|
||||
|
||||
$dotenv = Dotenv::createImmutable(__DIR__);
|
||||
$dotenv->load();
|
||||
$current_env = $_ENV;
|
||||
|
||||
if ($current_env["SCOUT_DRIVER"] === "typesense" && empty($current_env["TYPESENSE_API_KEY"])) {
|
||||
echo "Please set the TYPESENSE_API_KEY environment variable when setting SCOUT_DRIVER to typesense.";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$rrConfig = \Symfony\Component\Yaml\Yaml::parse(file_get_contents(".rr.yaml"));
|
||||
$rrConfig["http"]["pool"]["supervisor"]["max_worker_memory"] = (int) env("RR_MAX_WORKER_MEMORY", 128);
|
||||
$rrConfig["http"]["max_request_size"] = (int) env("RR_MAX_REQUEST_SIZE_MB", 256);
|
||||
$rrConfig["service"]["laravel_queue_worker_1"]["process_num"] = (int) env("JIKAN_QUEUE_WORKER_PROCESS_NUM", 1);
|
||||
$periodical_full_indexer_key = "JIKAN_ENABLE_PERIODICAL_FULL_INDEXER";
|
||||
if (array_key_exists($periodical_full_indexer_key, $current_env) && in_array($current_env[$periodical_full_indexer_key], [1, '1', 'true', 'True', 'TRUE'])) {
|
||||
$supercronic_schedule = file_get_contents("/etc/supercronic/laravel");
|
||||
$supercronic_schedule .= PHP_EOL;
|
||||
$supercronic_schedule .= "0 1 * * 1 php /app/artisan indexer:anime --fail && php /app/artisan indexer:anime --resume && php /app/artisan indexer:manga --fail && php /app/artisan indexer:manga --resume";
|
||||
$supercronic_schedule .= PHP_EOL;
|
||||
file_put_contents("/etc/supercronic/laravel", $supercronic_schedule);
|
||||
$current_time = time();
|
||||
echo json_encode(["level" => "info", "ts" => "$current_time.0", "logger" => "container_entrypoint", "msg" => "Full anime/manga indexer is enabled. They will run every Monday at 1am."]) . PHP_EOL;
|
||||
}
|
||||
file_put_contents(".rr.yaml", \Symfony\Component\Yaml\Yaml::dump($rrConfig, 8));
|
15
docker-entrypoint.sh
Executable file
15
docker-entrypoint.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
set -eo pipefail
|
||||
|
||||
status=0
|
||||
if [[ $# -eq 0 ]] ; then
|
||||
php /app/docker-entrypoint.php
|
||||
status=$?
|
||||
else
|
||||
php /app/docker-entrypoint.php "$@"
|
||||
status=$?
|
||||
fi
|
||||
|
||||
[[ $status -ne 0 ]] && exit $status
|
||||
|
||||
exec rr serve -c .rr.yaml
|
12
docker/base_image/php-8.0/Dockerfile
Normal file
12
docker/base_image/php-8.0/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM spiralscout/roadrunner:2.10.6 as roadrunner
|
||||
FROM composer:2.3.9 as composer
|
||||
FROM mlocati/php-extension-installer:1.5.29 as php-ext-installer
|
||||
FROM php:8.0-bullseye as runtime
|
||||
ARG GITHUB_PERSONAL_TOKEN
|
||||
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
||||
COPY --from=php-ext-installer /usr/bin/install-php-extensions /usr/local/bin/
|
||||
ENV COMPOSER_HOME="/tmp/composer"
|
||||
RUN install-php-extensions gd exif intl bz2 gettext mongodb-stable redis opcache sockets pcntl
|
||||
|
||||
# install roadrunner
|
||||
COPY --from=roadrunner /usr/bin/rr /usr/bin/rr
|
12
docker/base_image/php-8.1/Dockerfile
Normal file
12
docker/base_image/php-8.1/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM spiralscout/roadrunner:2.10.6 as roadrunner
|
||||
FROM composer:2.3.9 as composer
|
||||
FROM mlocati/php-extension-installer:1.5.29 as php-ext-installer
|
||||
FROM php:8.1-bullseye as runtime
|
||||
ARG GITHUB_PERSONAL_TOKEN
|
||||
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
||||
COPY --from=php-ext-installer /usr/bin/install-php-extensions /usr/local/bin/
|
||||
ENV COMPOSER_HOME="/tmp/composer"
|
||||
RUN install-php-extensions gd exif intl bz2 gettext mongodb-stable redis opcache sockets pcntl
|
||||
|
||||
# install roadrunner
|
||||
COPY --from=roadrunner /usr/bin/rr /usr/bin/rr
|
Loading…
x
Reference in New Issue
Block a user