Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide production Dockerfile, pullpreview workflow and docker-build-push workflow #31

Merged
merged 39 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b995b3c
provide a Dockerfile for production
mszulik Oct 26, 2023
ef58e40
only trigger on release
mszulik Oct 27, 2023
b56fc6d
also tag for major and minor
mszulik Oct 27, 2023
9d15bc2
add updated docker files and pullpreview configuration
mszulik Jan 15, 2024
a132a9f
provide a Dockerfile for production
mszulik Oct 26, 2023
71799ee
add updated docker files and pullpreview configuration
mszulik Jan 15, 2024
f372bda
use correct docker build context and reference Dockerfile
mszulik Jan 16, 2024
c032cd5
add a missing closing quoatation mark
mszulik Jan 16, 2024
1d3e9fd
remove commas when specifying who should have ssh access to pullprevi…
mszulik Jan 16, 2024
136769f
add keys to the .env values
mszulik Jan 16, 2024
064a3e9
use correct container name for mysql service
mszulik Jan 16, 2024
7c13596
remove basic auth for now
mszulik Jan 16, 2024
79a7372
also remove basic auth in traefik configuration
mszulik Jan 16, 2024
e8e3301
use a small lightsail instance since nano stop working completely whe…
mszulik Jan 16, 2024
8f8d4b8
try a medium instance
mszulik Jan 16, 2024
b59fa4f
add a seeder for pullpreview
mszulik Jan 17, 2024
ca9b3eb
fix an issue with env variables
mszulik Jan 17, 2024
c0db390
fix an issue where the query was executed to early
mszulik Jan 17, 2024
608ccd0
add the possibility to configure the amount of running workers
mszulik Jan 17, 2024
9be0a0b
use correct env variable in workers config
mszulik Jan 17, 2024
1f546c6
remove unnecessary events from pullpreview workflow
mszulik Jan 17, 2024
b88e282
simplify pullpreview workflow
mszulik Jan 17, 2024
bcf236a
update readme
mszulik Jan 17, 2024
ec27f70
use default command for mysql container
mszulik Jan 17, 2024
57efc36
remove .htpasswd volume
mszulik Jan 17, 2024
431b06f
remove traefik labels from development docker-compose.yml
mszulik Jan 17, 2024
1c34a2f
rename watchtower script to include lifecycle hook information
mszulik Jan 18, 2024
8c540fb
remove admins from pullpreview workflow as it defaults to collaborators
mszulik Jan 18, 2024
8af71b7
try setting admins explicitely to collaborators
mszulik Jan 18, 2024
c6fa02c
explicitly declare admin names since "@collaborators/push" doesn't wo…
mszulik Jan 18, 2024
b6bc366
update readme
mszulik Jan 18, 2024
60218f8
update readme
mszulik Jan 18, 2024
4ebce9c
clarify origin of .env variables in pullpreview workflow
mszulik Jan 19, 2024
e76c743
add a comment to clarify usage of LARAVEL_WORKERS_AMOUNT env variable
mszulik Jan 19, 2024
ffeeb61
clarify that the transmorpher auth token hash is only intended for pu…
mszulik Jan 19, 2024
4732824
rename supervisor program name for video transcoding workers
mszulik Jan 19, 2024
41c6951
rename laravel workers variable to be video transcoding specific
mszulik Jan 19, 2024
d6c9d50
update readme
mszulik Jan 22, 2024
1ee243a
update readme
mszulik Jan 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ DOCKER_CONTAINER_NAME=transmorpher
# Transmorpher
TRANSMORPHER_DEV_MODE=false
TRANSMORPHER_STORE_DERIVATIVES=true
TRANSMORPHER_DISK_ORIGINALS=s3Originals
TRANSMORPHER_DISK_IMAGE_DERIVATIVES=s3ImageDerivatives
TRANSMORPHER_DISK_VIDEO_DERIVATIVES=s3VideoDerivatives
TRANSMORPHER_DISK_ORIGINALS=localOriginals
TRANSMORPHER_DISK_IMAGE_DERIVATIVES=localImageDerivatives
TRANSMORPHER_DISK_VIDEO_DERIVATIVES=localVideoDerivatives
TRANSMORPHER_SIGNING_KEYPAIR=
TRANSMORPHER_OPTIMIZER_TIMEOUT=5
TRANSMORPHER_OPTIMIZER_TIMEOUT=10
LARAVEL_WORKERS_AMOUNT=1

# AWS
AWS_ACCESS_KEY_ID=
Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Docker Image CI

on:
release:
types: [published]

jobs:
build-push-docker-image:
runs-on: ubuntu-latest
steps:
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Checkout code
uses: actions/checkout@v4

- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
cybexwebdev/transmorpher
flavor: |
latest=auto
tags: |
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{version}}
type=sha

- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
file: ./docker/Dockerfile
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
40 changes: 40 additions & 0 deletions .github/workflows/pullpreview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: PullPreview
on:
pull_request:
types: [labeled, unlabeled, synchronize, closed, reopened]

jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # to fetch code (actions/checkout)
deployments: write # to delete deployments
pull-requests: write # to remove labels
statuses: write # to create commit status
steps:
- uses: actions/checkout@v4

- name: Generate .env file
env:
APP_KEY: ${{ secrets.APP_KEY }}
TRANSMORPHER_SIGNING_KEYPAIR: ${{ secrets.TRANSMORPHER_SIGNING_KEYPAIR }}
TRANSMORPHER_AUTH_TOKEN_HASH: ${{ secrets.TRANSMORPHER_AUTH_TOKEN_HASH }}
run: |
cp .env.example .env
echo "APP_KEY=$APP_KEY" >> .env
echo "TRANSMORPHER_SIGNING_KEYPAIR=$TRANSMORPHER_SIGNING_KEYPAIR" >> .env
echo "TRANSMORPHER_AUTH_TOKEN_HASH=$TRANSMORPHER_AUTH_TOKEN_HASH" >> .env

- uses: pullpreview/action@v5
with:
admins: jheusinger, gael-connan-cybex, holyfabi, lupinitylabs, mszulik
cidrs: "0.0.0.0/0"
compose_files: docker-compose.pullpreview.yml
default_port: 80
instance_type: medium
ports: 80, 443
env:
AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}"
AWS_REGION: "eu-central-1"
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,29 @@ A media server for images and videos.

## Installation

### Using docker

See the [Docker Hub repository](https://hub.docker.com/r/cybexwebdev/transmorpher) for images.

To not accidentally upgrade to a new major version, attach the major version you want to use to the image name:

`cybexwebdev/transmorpher:0`

#### Configuration options

There needs to be at least 1 Laravel worker to transcode videos. The following variable specifies how many workers should be running in the container:

```dotenv
LARAVEL_WORKERS_AMOUNT=1
```

This environment variable has to be passed to the app container in your docker-compose.yml:

```yaml
environment:
LARAVEL_WORKERS_AMOUNT: ${LARAVEL_WORKERS_AMOUNT:-1}
```

### Cloning the repository

To clone the repository and get your media server running use:
Expand Down Expand Up @@ -389,6 +412,33 @@ You will also have to adjust the configuration value:
'transcode_class' => App\Classes\YourTranscodeClass::class,
```

## Development

### [Pullpreview](https://github.com/pullpreview/action)

When labeling a pull request with the "pullpreview" label, a staging environment is booted. To make this functional, some environment variables have to be stored in GitHub secrets:

- APP_KEY
- TRANSMORPHER_SIGNING_KEYPAIR
- TRANSMORPHER_AUTH_TOKEN_HASH
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY

#### Auth Token Hash

The environment is seeded with a user with an auth token. To get access, you will have to locally create a token and use this token and its hash.

```bash
php artisan create:user pullpreview [email protected]
```

Take the hash of the token from the `personal_access_tokens` table and save it to GitHub secrets. The command also provides a `TRANSMORPHER_AUTH_TOKEN`, which should be stored
securely to use in client systems.

#### AWS Credentials

You need credentials of an IAM user that can manage AWS Lightsail. For a recommended configuration take a look at the [Pullpreview wiki](https://github.com/pullpreview/action/wiki/Recommended-AWS-Configuration).

## License

The Transmorpher media server is licensed under the [MIT license](https://opensource.org/licenses/MIT).
22 changes: 22 additions & 0 deletions database/seeders/PullpreviewSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Database\Seeders;

use Artisan;
use DB;
use Illuminate\Database\Seeder;

class PullpreviewSeeder extends Seeder
{
/**
* Seeds the database with a default user used within a Pullpreview environment.
*
* @return void
*/
public function run(): void
{
Artisan::call('create:user pullpreview [email protected]');

DB::table('personal_access_tokens')->where('id', 1)->update(['token' => env('TRANSMORPHER_AUTH_TOKEN_HASH')]);
}
}
85 changes: 85 additions & 0 deletions docker-compose.pullpreview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
version: '3.8'
services:
app:
container_name: ${APP_CONTAINER_NAME:-transmorpher}
build:
context: .
dockerfile: ./docker/Dockerfile
networks:
- traefik
- internal
depends_on:
mysql:
condition: service_healthy
traefik:
condition: service_started
environment:
PULLPREVIEW: true
PULLPREVIEW_FIRST_RUN: ${PULLPREVIEW_FIRST_RUN}
LARAVEL_WORKERS_AMOUNT: ${LARAVEL_WORKERS_AMOUNT:-1}
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.${APP_CONTAINER_NAME:-transmorpher}.rule=Host(`${PULLPREVIEW_PUBLIC_DNS}`)'
- 'traefik.http.routers.${APP_CONTAINER_NAME:-transmorpher}.tls=true'
- 'traefik.http.routers.${APP_CONTAINER_NAME:-transmorpher}.tls.certresolver=production'
mysql:
image: 'mysql/mysql-server:8.0'
container_name: ${MYSQL_CONTAINER_NAME:-transmorpher-mysql-1}
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 1
volumes:
- 'mysql:/var/lib/mysql'
networks:
- internal
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}" ]
retries: 3
timeout: 5s
traefik:
image: traefik:v2.10
container_name: ${TRAEFIK_CONTAINER_NAME:-transmorpher-traefik}
ports:
- '80:80'
- '443:443'
environment:
TRAEFIK_GLOBAL_SENDANONYMOUSUSAGE: false
TRAEFIK_API: false
TRAEFIK_API_DASHBOARD: false
TRAEFIK_CERTIFICATESRESOLVERS_PRODUCTION: true
TRAEFIK_CERTIFICATESRESOLVERS_PRODUCTION_ACME_EMAIL: '[email protected]'
TRAEFIK_CERTIFICATESRESOLVERS_PRODUCTION_ACME_CASERVER: 'https://acme-v02.api.letsencrypt.org/directory'
TRAEFIK_CERTIFICATESRESOLVERS_PRODUCTION_ACME_STORAGE: '/letsencrypt/acme.json'
TRAEFIK_CERTIFICATESRESOLVERS_PRODUCTION_ACME_HTTPCHALLENGE: true
TRAEFIK_CERTIFICATESRESOLVERS_PRODUCTION_ACME_HTTPCHALLENGE_ENTRYPOINT: web
TRAEFIK_ENTRYPOINTS_WEB: true
TRAEFIK_ENTRYPOINTS_WEB_ADDRESS: ':80'
TRAEFIK_ENTRYPOINTS_WEB_HTTP: true
TRAEFIK_ENTRYPOINTS_WEB_HTTP_REDIRECTIONS_ENTRYPOINT_TO: websecure
TRAEFIK_ENTRYPOINTS_WEB_HTTP_REDIRECTIONS_ENTRYPOINT_SCHEME: https
TRAEFIK_ENTRYPOINTS_WEBSECURE: true
TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS: ':443'
TRAEFIK_PROVIDERS_DOCKER: true
TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: false
TRAEFIK_PROVIDERS_DOCKER_NETWORK: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
networks:
- traefik

networks:
internal:
internal: true
traefik:
name: traefik

volumes:
mysql:
driver: local
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# For more information: https://laravel.com/docs/sail
version: '3'
version: '3.8'
services:
app:
container_name: ${DOCKER_CONTAINER_NAME:-transmorpher}
Expand Down
30 changes: 30 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM webdevops/php-nginx:8.2

WORKDIR /var/www/html

ENV WEB_DOCUMENT_ROOT /var/www/html/public

# Timeout for the post update script in minutes.
LABEL com.centurylinklabs.watchtower.lifecycle.post-update-timeout="1440"
# Watchtower will run this script after restarting the updated container.
LABEL com.centurylinklabs.watchtower.lifecycle.post-update="/var/www/html/docker/watchtower.post-update.sh"

COPY . /var/www/html
COPY ./docker/workers.conf /opt/docker/etc/supervisor.d/

RUN composer install --no-interaction --no-dev

RUN chmod +x /var/www/html/docker/entryfile.sh
RUN chmod +x /var/www/html/docker/watchtower.post-update.sh
RUN chmod 755 -R /var/www/html/storage
RUN chown -R application:application /var/www/html/storage

RUN php /var/www/html/artisan storage:link

RUN apt update
RUN apt install -y imagemagick jpegoptim optipng pngquant gifsicle webp ffmpeg

RUN docker-service-enable cron
RUN docker-cronjob '0 2 * * * application php /var/www/html/artisan ffmpeg:delete-temp'

ENTRYPOINT ["/var/www/html/docker/entryfile.sh"]
11 changes: 11 additions & 0 deletions docker/entryfile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

if ${PULLPREVIEW:-false}; then
php /var/www/html/artisan migrate --force

if ${PULLPREVIEW_FIRST_RUN:-false}; then
php /var/www/html/artisan db:seed --class=PullpreviewSeeder --force
fi
fi

exec /entrypoint supervisord "$@"
3 changes: 3 additions & 0 deletions docker/watchtower.post-update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

php /var/www/html/artisan migrate --force
11 changes: 11 additions & 0 deletions docker/workers.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work --queue=video-transcoding
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
gael-connan-cybex marked this conversation as resolved.
Show resolved Hide resolved
numprocs=%(ENV_LARAVEL_WORKERS_AMOUNT)s
redirect_stderr=true
stdout_logfile=/dev/stdout
stopwaitsecs=10801
Loading