Fly Deploy not limiting regions

Using fly deploy --region xxx is deploying the build to all my app regions.

The desired result is a deployment to only the app in region xxx…

I adjust some configuration files depending on if the region is my primary or replica apps and need to ensure the files are deployed to the correct servers.

I’m not sure it is actually possible to deploy to just one region if your app runs in multiple ones :thinking:. Only all the apps I’ve come across have matching vms across all regions and they all get replaced. In which case the only way to deploy to one region is to only run in one region.

If you want to have different config depending on where the code is running, that is do-able though. Just with a different approach. The way Fly says to do it is specify your primary region in an environment variable. So that can go in your fly.toml in an [env] block. And then your code can check that environment variable and proceed accordingly. Such as here, where I picked the database connection depending on whether the config code was running in the primary region (say, lhr) or not. The FLY_REGION env is provided by Fly so your code knows which region it is running in:

1 Like

Yeah, that is the approach I tried first. In Laravel, my jobs and commands are scheduled in the app/Console/Kernel.php file. I have a config file that loads the region 'server-region' => env('FLY_REGION'), however this env seems to only be available when the server has an active user session or a login shell active. In my Kernel.php file I wrap the commands I want run like this :::

        if (config('aeroquote.server-region') == 'dfw') {

            $schedule->job(new StorageTest())->everyFourMinutes();

            $schedule->job(new FileTestJob())->everyFourMinutes();

My ideal would be to have a truthy var set as you mentioned: env('FLY_REGION') == env('PRIMARY_REGION') but this doesn’t seem to be available to the processes run via the cron…

I know @fideloper-fly is working on new docker setup for Laravel, maybe ill wait to see what come from that.

If you want to “lock” your app to deploying to only one region, you probably want to use a volume to do it. I describe this in an answer to another question here: Regional data "lock"? - #6 by ajsharp

Hope this helps. Cheers.

1 Like

Hmm. Yeah, @ajsharp makes a good point that you can make your app run in one region. Which would avoid the need to compare FLY_REGION and PRIMARY_REGION. Since there would only be one region.

But you should also be able to get that dynamic env approach to work too. I forget the innards but I wonder if environment variables are cleared using the CLI commands :thinking:. Only I recall I had lots of “fun” and eventually realised to get environment variables passed in from the system (like FLY_REGION) I needed the clear_env = no line below. That’s part of php-fpm’s conf (used by web requests etc). As you say, the Laravel stuff is being updated this week so the approach may change and your issue may be solved automatically as a result:

1 Like

Oh, that sounds very close to the “cant see ENVs from jobs” issue I’m having, do you have a preferred way to ensure that is set in the docker files on my deployment ?

Thanks @ajsharp and @greg but I do want the multi-region feature for this app. I am mounting volumes to my apps in each region (but haven’t found a good use case for them yet)

1 Like

I am using swoole BTW…

@TomWhite1 Ah. Yes, totally understandable wanting multi-region. That’s one of the main reasons for using Fly :slight_smile:

I don’t know what conf/settings @fideloper-fly is using for Swoole now, so I can’t say how to ensure what you need is set for your deployment. The hello-world app was nginx/php-fpm. So it may be a case of waiting for those latest changes (this week, I believe) and then trying again. May get solved without you needing to do anything. If not, at least you’ll have the latest code and docs to debug from.

@TomWhite1 can you share your Dockerfile? I’m curious what “version” of the generated Docker setup you have.

There was, at one point, a condition where the way CRON was run wouldn’t allow environment variables through (specifically the use of su, e.g.: su -c "cron command here" - app... caused an issue - env vars weren’t accessible to the cron task in this version).

Hi this is what i HAD. I have since used your new docker image but still working out how to construct the docker yaml file (that didn’t get generated?).

Old Docker from Alpine image:

# syntax = docker/dockerfile:experimental
FROM alpine:3.16 as base

LABEL fly_launch_runtime="laravel"

# Add jpegoptim optipng pngquant gifsicle libraries...
RUN apk --update add jpegoptim
RUN apk --update add optipng
RUN apk --update add pngquant
RUN apk --update add gifsicle

RUN apk update \
    && apk add curl zip unzip tzdata supervisor nginx htop vim ca-certificates rsync \
           php81           php81-cli        php8-pecl-mcrypt \
           php81-soap      php81-openssl    php81-gmp \
           php81-pdo_odbc  php81-json       php81-dom \
           php81-pdo       php81-zip        php81-pdo_mysql \
           php81-sqlite3   php81-pdo_pgsql  php81-bcmath \
           php81-gd        php81-odbc       php81-pdo_sqlite \
           php81-gettext   php81-xmlreader  php81-bz2 \
           php81-iconv     php81-pdo_dblib  php81-curl \
           php81-ctype     php81-phar       php81-xml \
           php81-common    php81-mbstring   php81-tokenizer \
           php81-xmlwriter php81-fileinfo   php81-opcache \
           php81-simplexml php81-pecl-redis php81-sockets \
           redis \
           php81-pcntl     php81-posix      php81-pecl-swoole \
           php81-fpm       php81-pecl-imagick-dev \
           php81-pecl-imagick \
           php81-exif      php81-gd         php81-intl \
           php81-bcmath    ghostscript\
    && ln -sf /usr/bin/php81 /usr/bin/php \
    && cp /etc/nginx/nginx.conf /etc/nginx/nginx.old.conf \
    && rm -rf /etc/nginx/http.d/default.conf \
    && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
    && adduser -D -u 1000 -g 'app' app \
    && addgroup nginx app \
    && mkdir -p /var/run/php \
    && chown -R app:app /var/run/php \
    && mkdir -p /var/www/html

WORKDIR /var/www/html
# copy application code, skipping files based on .dockerignore
COPY . /var/www/html

# Clear the event cache prior to composer install
RUN php artisan event-sourcing:clear-event-handlers

# Install dependencies, configure server
RUN composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader \
    && mkdir -p storage/logs \
    && chown -R app:app /var/www/html \
    && /usr/bin/crontab docker/crontab \
    && mv docker/supervisor.conf /etc/supervisord.conf \
    && mv docker/nginx.conf /etc/nginx/nginx.conf \
    && mv docker/server.conf /etc/nginx/server.conf \
    && mv docker/php.ini /etc/php81/conf.d/php.ini \
    && sed -i 's/protected \$proxies/protected \$proxies = "*"/g' app/Http/Middleware/TrustProxies.php

# If we're not using Octane, configure php-fpm
RUN if ! grep -Fq "laravel/octane" /var/www/html/composer.json; then \
        rm -rf /etc/php81/php-fpm.conf; \
        rm -rf /etc/php81/php-fpm.d/www.conf; \
        mv docker/php-fpm.conf /etc/php81/php-fpm.conf; \
        mv docker/app.conf /etc/php81/php-fpm.d/app.conf; \
    elif grep -Fq "spiral/roadrunner" /var/www/html/composer.json; then \
        if [ -f ./vendor/bin/rr ]; then ./vendor/bin/rr get-binary; fi; \
        rm -f .rr.yaml; \
    fi

# clear Laravel cache that may be left over
RUN composer dump-autoload \
    && php artisan optimize:clear \
    && chmod -R ug+w /var/www/html/storage \
    && chmod -R 755 /var/www/html

# Cache the event handlers
RUN php artisan event-sourcing:cache-event-handler

# Multi-stage build: Build static assets
FROM node:14 as node_modules_go_brrr

# Add the `svgo` Library...
RUN npm install -g svgo

RUN mkdir /app

RUN mkdir -p  /app
WORKDIR /app
COPY . .
RUN if [ -f "yarn.lock" ]; then \
        yarn install; \
    elif [ -f "package-lock.json" ]; then \
        npm ci --no-audit && npm run prod; \
    else \
        npm install && npm run prod; \
    fi

# Create final container, adding in static assets
FROM base

COPY --from=node_modules_go_brrr /app/public /var/www/html/public-npm
RUN rsync -ar /var/www/html/public-npm/ /var/www/html/public/ \
    && rm -rf /var/www/html/public-npm

# The same port nginx.conf is set to listen on and fly.toml references (standard is 8080)
EXPOSE 8080

ENTRYPOINT ["/var/www/html/docker/run.sh"]


And this was the generated cron :::

* * * * * /bin/su -c "/usr/bin/php /var/www/html/artisan schedule:run" - app > /proc/1/fd/1 2>&1

Gotcha, yep that’ll be an issue! I saw/answered your other question, which I think might be the better place to address this!

I have deployed new app images based on the GitHub - serversideup/docker-php: Production-ready Docker images for PHP. Optimized for Laravel, WordPress, and more! by @fideloper-fly . The config values and ENV are available to the jobs, but not if I deploy using Laravel Octane (swoole). It seems bypassing the php-fpm load is not allowing ENV to be accessible to the cron processes…

Its not a big deal to drop Octane for my app as we don’t serve up huge numbers of requests.