From bfdae4339c6493df933f55285c4946dd0315574f Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Mon, 20 Mar 2023 14:04:35 +0000 Subject: [PATCH] Have Sail and SSU. Runs a command on a remote host. --- .env.example | 5 +- app/Http/Livewire/RunCommand.php | 32 ++++--- app/Jobs/ExecuteCoolifyProcess.php | 36 ++++--- app/Services/CoolifyProcess.php | 14 +-- coolify_id25519 | 7 -- docker-compose.yaml | 11 ++- docker/dev/Dockerfile | 93 +++++++++++++++++-- docker/dev/php.ini | 4 + docker/dev/start-container | 17 ++++ docker/dev/supervisord.conf | 27 ++++++ docker/staging/Dockerfile | 20 ++++ .../etc/s6-overlay/s6-rc.d/queue-worker/run | 0 .../etc/s6-overlay/s6-rc.d/queue-worker/type | 0 .../s6-rc.d/user/contents.d/queue-worker | 0 .../views/livewire/run-command.blade.php | 45 ++++++--- 15 files changed, 234 insertions(+), 77 deletions(-) delete mode 100644 coolify_id25519 create mode 100644 docker/dev/php.ini create mode 100644 docker/dev/start-container create mode 100644 docker/dev/supervisord.conf create mode 100644 docker/staging/Dockerfile rename docker/{dev => staging}/etc/s6-overlay/s6-rc.d/queue-worker/run (100%) rename docker/{dev => staging}/etc/s6-overlay/s6-rc.d/queue-worker/type (100%) rename docker/{dev => staging}/etc/s6-overlay/s6-rc.d/user/contents.d/queue-worker (100%) diff --git a/.env.example b/.env.example index f6b965c91..952d224e9 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,7 @@ GROUPID= ############################################################################################################ APP_NAME=Laravel +APP_SERVICE=php APP_ENV=local APP_KEY= APP_DEBUG=true @@ -17,7 +18,7 @@ DB_CONNECTION=pgsql DB_HOST=postgres DB_PORT=5432 DB_DATABASE=coolify -DB_USERNAME=sail +DB_USERNAME=coolify DB_PASSWORD=password -QUEUE_CONNECTION=redis +QUEUE_CONNECTION=database diff --git a/app/Http/Livewire/RunCommand.php b/app/Http/Livewire/RunCommand.php index e99ca0da1..11dad0893 100755 --- a/app/Http/Livewire/RunCommand.php +++ b/app/Http/Livewire/RunCommand.php @@ -12,7 +12,7 @@ class RunCommand extends Component public $manualKeepAlive = false; - public $command = ''; + public $command = 'ls'; public function render() { @@ -21,30 +21,32 @@ public function render() public function runCommand() { - // TODO Execute with Livewire Normally - $this->activity = coolifyProcess($this->command, 'testing-host'); - + $this->isKeepAliveOn = true; // Override manual to experiment -// $sleepingBeauty = 'x=1; while [ $x -le 40 ]; do sleep 0.1 && echo "Welcome $x times" $(( x++ )); done'; -// -// $commandString = <<activity = coolifyProcess($commandString, 'testing-host'); + $override = 0; + if($override) { + // Good to play with the throttle feature + $sleepingBeauty = 'x=1; while [ $x -le 40 ]; do sleep 0.1 && echo "Welcome $x times" $(( x++ )); done'; - $this->isKeepAliveOn = true; + $this->activity = coolifyProcess(<<activity = coolifyProcess($this->command, 'testing-host'); } public function polling() { $this->activity?->refresh(); - if ($this->activity?->properties['status'] === 'finished') { + if (data_get($this->activity, 'properties.exitCode') !== null) { $this->isKeepAliveOn = false; } } diff --git a/app/Jobs/ExecuteCoolifyProcess.php b/app/Jobs/ExecuteCoolifyProcess.php index 9c9a10771..18e1715b9 100755 --- a/app/Jobs/ExecuteCoolifyProcess.php +++ b/app/Jobs/ExecuteCoolifyProcess.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use App\Services\ProcessStatus; use Illuminate\Support\Facades\DB; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeUnique; @@ -11,7 +12,6 @@ use Illuminate\Process\ProcessResult; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Process; use Spatie\Activitylog\Contracts\Activity; @@ -43,8 +43,7 @@ public function __construct( */ public function handle(): ?ProcessResult { - ray()->clearAll(); - $this->timeStart = $start = hrtime(true); + $this->timeStart = hrtime(true); $user = $this->activity->getExtraProperty('user'); $destination = $this->activity->getExtraProperty('destination'); @@ -53,24 +52,16 @@ public function handle(): ?ProcessResult $delimiter = 'EOF-COOLIFY-SSH'; - File::chmod(base_path('coolify_id25519'), 0600); - $sshCommand = 'ssh ' - . '-i ./coolify_id25519 ' . '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ' . '-o PasswordAuthentication=no ' + . "-p {$port} " . "{$user}@{$destination} " . " 'bash -se' << \\$delimiter" . PHP_EOL . $command . PHP_EOL . $delimiter; -// $sshCommand = "whoami ; pwd ; ls "; - - $process = Process::start( - $sshCommand, - $this->handleOutput(...), - ); - + $process = Process::start($sshCommand, $this->handleOutput(...)); $res = $process->wait(); @@ -78,13 +69,20 @@ public function handle(): ?ProcessResult return $res; } - - // TODO Why is this not persisting?? Immutable property?? - $this->activity->properties->put('pid', $process->id()); - $this->activity->properties->put('exitCode', $res->exitCode()); - $this->activity->properties->put('stdout', $res->output()); - $this->activity->properties->put('stderr', $res->errorOutput()); + $status = match ($res->exitCode()) { + 0 => ProcessStatus::FINISHED, + default => ProcessStatus::ERROR, + }; + + $this->activity->properties = $this->activity->properties->merge([ + 'exitCode' => $res->exitCode(), + 'stdout' => $res->output(), + 'stderr' => $res->errorOutput(), + 'status' => $status, + ]); + $this->activity->save(); + return $res; } diff --git a/app/Services/CoolifyProcess.php b/app/Services/CoolifyProcess.php index bc21bda98..16071ebd7 100644 --- a/app/Services/CoolifyProcess.php +++ b/app/Services/CoolifyProcess.php @@ -19,12 +19,14 @@ public function __construct( protected ?string $user = 'root', ){ $this->activity = activity() - ->withProperty('type', 'COOLIFY_PROCESS') - ->withProperty('user', $this->user) - ->withProperty('destination', $this->destination) - ->withProperty('port', $this->port) - ->withProperty('command', $this->command) - ->withProperty('status', ProcessStatus::HOLDING) + ->withProperties([ + 'type' => 'COOLIFY_PROCESS', + 'user' => $this->user, + 'destination' => $this->destination, + 'port' => $this->port, + 'command' => $this->command, + 'status' => ProcessStatus::HOLDING, + ]) ->log("Awaiting to start command...\n\n"); } diff --git a/coolify_id25519 b/coolify_id25519 deleted file mode 100644 index c67d90a64..000000000 --- a/coolify_id25519 +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW -QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk -hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA -AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV -uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== ------END OPENSSH PRIVATE KEY----- diff --git a/docker-compose.yaml b/docker-compose.yaml index 9fe23b25f..39a1537e3 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,15 +3,18 @@ services: php: image: coolify:4 build: - dockerfile: Dockerfile context: ./docker/dev + dockerfile: Dockerfile + args: + WWWGROUP: '${WWWGROUP}' ports: - "${APP_PORT:-8000}:80" - "${VITE_PORT:-5173}:${VITE_PORT:-5173}" environment: - PUID: "${USERID:-9999}" - PGID: "${GROUPID:-9999}" - SSL_MODE: 'off' + WWWUSER: "${WWWUSER}" + LARAVEL_SAIL: 1 + XDEBUG_MODE: "${SAIL_XDEBUG_MODE:-off}" + XDEBUG_CONFIG: "${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}" volumes: - .:/var/www/html networks: diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index ccfda8f89..239bf9fa8 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -1,20 +1,93 @@ -FROM serversideup/php:8.2-fpm-nginx +FROM ubuntu:22.04 + +ARG WWWGROUP +ARG TARGETPLATFORM ARG NODE_VERSION=18 -ARG POSTGRES_VERSION=15 +ARG POSTGRES_VERSION=14 + +# https://download.docker.com/linux/static/stable/ +ARG DOCKER_VERSION=20.10.18 +# https://github.com/docker/compose/releases +# Reverted to 2.6.1 because of this https://github.com/docker/compose/issues/9704. 2.9.0 still has a bug. +ARG DOCKER_COMPOSE_VERSION=2.6.1 +# https://github.com/buildpacks/pack/releases +ARG PACK_VERSION=v0.27.0 + +WORKDIR /var/www/html + +ENV DEBIAN_FRONTEND noninteractive +ENV TZ=UTC + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN apt-get update \ + && apt-get install -y gnupg gosu curl ca-certificates zip unzip git git-lfs supervisor sqlite3 libcap2-bin libpng-dev python2 dnsutils \ + && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x14aa40ec0831756756d7f66c4f4ea0aae5267a6c' | gpg --dearmor | tee /usr/share/keyrings/ppa_ondrej_php.gpg > /dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ + && apt-get update \ + && apt-get install -y php8.2-cli php8.2-dev \ + php8.2-pgsql php8.2-sqlite3 php8.2-gd \ + php8.2-curl \ + php8.2-imap php8.2-mysql php8.2-mbstring \ + php8.2-xml php8.2-zip php8.2-bcmath php8.2-soap \ + php8.2-intl php8.2-readline \ + php8.2-ldap \ + php8.2-msgpack php8.2-igbinary php8.2-redis php8.2-swoole \ + php8.2-memcached php8.2-pcov php8.2-xdebug \ + && php -r "readfile('https://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \ && curl -sLS https://deb.nodesource.com/setup_$NODE_VERSION.x | bash - \ && apt-get install -y nodejs \ - && npm install -g npm - -RUN apt-get install -y php-pgsql openssh-client - -RUN apt-get -y autoremove \ + && npm install -g npm \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarn.gpg >/dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ + && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/pgdg.gpg >/dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ + && apt-get update \ + && apt-get install -y yarn \ + && apt-get install -y mysql-client \ + && apt-get install -y postgresql-client-$POSTGRES_VERSION \ + && apt-get -y autoremove \ && apt-get clean \ - && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.2 + +RUN groupadd --force -g $WWWGROUP sail +RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail + +USER sail +RUN mkdir -p ~/.ssh +RUN echo "-----BEGIN OPENSSH PRIVATE KEY-----\n\ +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n\ +QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk\n\ +hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA\n\ +AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV\n\ +uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==\n\ +-----END OPENSSH PRIVATE KEY-----" >> ~/.ssh/id_ed25519 +RUN chmod 0600 ~/.ssh/id_ed25519 USER root -# S6 Overlay config -COPY --chmod=755 etc/s6-overlay/ /etc/s6-overlay/ +COPY start-container /usr/local/bin/start-container +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY php.ini /etc/php/8.2/cli/conf.d/99-sail.ini +RUN chmod +x /usr/local/bin/start-container + +# Install Docker CLI, Docker Compose, and Pack +RUN mkdir -p ~/.docker/cli-plugins +RUN curl -SL https://cdn.coollabs.io/bin/$TARGETPLATFORM/docker-$DOCKER_VERSION -o /usr/bin/docker +RUN curl -SL https://cdn.coollabs.io/bin/$TARGETPLATFORM/docker-compose-linux-$DOCKER_COMPOSE_VERSION -o ~/.docker/cli-plugins/docker-compose -o /home/sail/.docker/cli-plugins/docker-compose +RUN curl -SL https://cdn.coollabs.io/bin/$TARGETPLATFORM/pack-$PACK_VERSION -o /usr/local/bin/pack +RUN curl -sSL https://nixpacks.com/install.sh | bash + +RUN chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack +RUN chmod +x /usr/local/bin/pack + +RUN mkdir -p /home/sail/.docker/cli-plugins +RUN cp ~/.docker/cli-plugins/docker-compose /home/sail/.docker/cli-plugins/docker-compose +RUN chown -R sail:sail /home/sail + +EXPOSE 8000 + +ENTRYPOINT ["start-container"] diff --git a/docker/dev/php.ini b/docker/dev/php.ini new file mode 100644 index 000000000..66d04d5be --- /dev/null +++ b/docker/dev/php.ini @@ -0,0 +1,4 @@ +[PHP] +post_max_size = 100M +upload_max_filesize = 100M +variables_order = EGPCS diff --git a/docker/dev/start-container b/docker/dev/start-container new file mode 100644 index 000000000..b86439907 --- /dev/null +++ b/docker/dev/start-container @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +if [ ! -z "$WWWUSER" ]; then + usermod -u $WWWUSER sail +fi + +if [ ! -d /.composer ]; then + mkdir /.composer +fi + +chmod -R ugo+rw /.composer + +if [ $# -gt 0 ]; then + exec gosu $WWWUSER "$@" +else + exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf +fi diff --git a/docker/dev/supervisord.conf b/docker/dev/supervisord.conf new file mode 100644 index 000000000..a2ff48927 --- /dev/null +++ b/docker/dev/supervisord.conf @@ -0,0 +1,27 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php] +command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80 +user=sail +environment=LARAVEL_SAIL="1" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:laravel-worker] +process_name=%(program_name)s_%(process_num)02d +command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan queue:listen +user=sail +autostart=true +autorestart=true +stopasgroup=true +killasgroup=true +numprocs=8 +redirect_stderr=true +stdout_logfile=/var/www/html/storage/logs/worker.log +stopwaitsecs=3600 diff --git a/docker/staging/Dockerfile b/docker/staging/Dockerfile new file mode 100644 index 000000000..ccfda8f89 --- /dev/null +++ b/docker/staging/Dockerfile @@ -0,0 +1,20 @@ +FROM serversideup/php:8.2-fpm-nginx + +ARG NODE_VERSION=18 +ARG POSTGRES_VERSION=15 + +RUN apt-get update \ + && curl -sLS https://deb.nodesource.com/setup_$NODE_VERSION.x | bash - \ + && apt-get install -y nodejs \ + && npm install -g npm + +RUN apt-get install -y php-pgsql openssh-client + +RUN apt-get -y autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + +USER root + +# S6 Overlay config +COPY --chmod=755 etc/s6-overlay/ /etc/s6-overlay/ diff --git a/docker/dev/etc/s6-overlay/s6-rc.d/queue-worker/run b/docker/staging/etc/s6-overlay/s6-rc.d/queue-worker/run similarity index 100% rename from docker/dev/etc/s6-overlay/s6-rc.d/queue-worker/run rename to docker/staging/etc/s6-overlay/s6-rc.d/queue-worker/run diff --git a/docker/dev/etc/s6-overlay/s6-rc.d/queue-worker/type b/docker/staging/etc/s6-overlay/s6-rc.d/queue-worker/type similarity index 100% rename from docker/dev/etc/s6-overlay/s6-rc.d/queue-worker/type rename to docker/staging/etc/s6-overlay/s6-rc.d/queue-worker/type diff --git a/docker/dev/etc/s6-overlay/s6-rc.d/user/contents.d/queue-worker b/docker/staging/etc/s6-overlay/s6-rc.d/user/contents.d/queue-worker similarity index 100% rename from docker/dev/etc/s6-overlay/s6-rc.d/user/contents.d/queue-worker rename to docker/staging/etc/s6-overlay/s6-rc.d/user/contents.d/queue-worker diff --git a/resources/views/livewire/run-command.blade.php b/resources/views/livewire/run-command.blade.php index fe24caab3..782b5c309 100755 --- a/resources/views/livewire/run-command.blade.php +++ b/resources/views/livewire/run-command.blade.php @@ -6,7 +6,7 @@