A few days ago I noticed that one of my side projects hosted on Heroku was not running anymore.
The reason : No more free tier...
It was time to find an alternative to host my app for free.
Why Fly ?
There is not reason for that choice beside the fact that it manage to host my app for free.
Versions
My app is a Symfony 5.3 API, running with PHP 7.4
Dockerfile
Fly.io does have an integration for laravel but none for Symfony.
I had to find/create a Dockerfile.
I found some great ressources but none of them worked out of the box.
looking at this repo helped me : https://github.com/fly-apps/fly-hello-laravel/blob/main/Dockerfile
This is my edited Dockerfile
FROM alpine:3.14
LABEL fly_launch_runtime="Symfony"
RUN apk update
# add useful utilities
RUN apk add curl \
zip \
unzip \
ssmtp \
tzdata \
openssl
# php, with assorted extensions we likely need
RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ --allow-untrusted gnu-libiconv \
&& apk add -U --no-cache \
# Packages
tini \
php7 \
php7-amqp \
php7-dev \
php7-common \
php7-apcu \
php7-gd \
php7-xmlreader \
php7-bcmath \
php7-ctype \
php7-curl \
php7-exif \
php7-iconv \
php7-intl \
php7-json \
php7-mbstring \
php7-opcache \
php7-openssl \
php7-pcntl \
php7-pdo \
php7-mysqlnd \
php7-pdo_mysql \
php7-pdo_pgsql \
php7-phar \
php7-posix \
php7-session \
php7-xml \
php7-xsl \
php7-zip \
php7-zlib \
php7-dom \
php7-redis \
php7-fpm \
php7-sodium \
php7-tokenizer
# supervisor, to support running multiple processes in a single app
RUN apk add supervisor
# nginx (https://wiki.alpinelinux.org/wiki/Nginx)
RUN apk add nginx
# ... with custom conf
RUN cp /etc/nginx/nginx.conf /etc/nginx/nginx.old.conf && rm -rf /etc/nginx/http.d/default.conf
# htop, which is useful if need to SSH in to the vm
RUN apk add htop
# composer, to install Laravel's dependencies
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# add users (see https://www.getpagespeed.com/server-setup/nginx-and-php-fpm-what-my-permissions-should-be)
# 1. a user for the app and php-fpm to interact with it (execute)
RUN adduser -D -u 1000 -g 'app' app
# 2. a user for nginx is not needed because already have one
# ... and add the nginx user TO the app group else it won't have permission to access web files (as can see in /var/log/nginx/error.log)
RUN addgroup nginx app
# use a socket not port for php-fpm so php-fpm needs permission to write to thay folder (make sure the same .sock is in nginx.conf and in php-fpm's app.conf)
RUN mkdir /var/run/php && chown -R app:app /var/run/php
# working directory
RUN mkdir /var/www/html
WORKDIR /var/www/html
# copy app code across, skipping files based on .dockerignore
COPY . /var/www/html
# ... install Laravel dependencies
RUN composer install
# ... and make all files owned by app, including the just added /vendor
RUN chown -R app:app /var/www/html
# move the docker-related conf files out of the app folder to where on the vm they need to be
RUN rm -rf /etc/php7/php-fpm.conf
RUN rm -rf /etc/php7/php-fpm.d/www.conf
RUN mv docker/supervisor.conf /etc/supervisord.conf
RUN mv docker/nginx.conf /etc/nginx/nginx.conf
RUN mv docker/php.ini /etc/php7/conf.d/php.ini
RUN mv docker/php-fpm.conf /etc/php7/php-fpm.conf
RUN mv docker/app.conf /etc/php7/php-fpm.d/app.conf
# make sure can execute php files (since php-fpm runs as app, it needs permission e.g for /storage/framework/views for caching views)
RUN chmod -R 755 /var/www/html
# the same port nginx.conf is set to listen on and fly.toml references (standard is 8080)
EXPOSE 8080
# off we go (since no docker-compose, keep both nginx and php-fpm running in the same container by using supervisor) ...
ENTRYPOINT ["supervisord", "-c", "/etc/supervisord.conf"]
I you want php8, just replace php7 with php8. (docker's magic)
I made a git repo if you want to browse the files of my 'docker' folder.
Databse
My database is hosted on a tinny VPS, so I didn't had to do anything.
If you want to host your db on fly, they offer free 3GB
postgres.
Alternative
I didn't tried Fly : turboku launcher, but it may be a simpler way to migrate.
see : https://fly.io/launch/heroku
With dockerfile your a not tied to a particular host, and can migrate smoothly between them.
Conclusion
If you are looking to migrate your Heroku app, save yourself a couple of hours and take a look at my repo : https://github.com/Thomas-Philippot/symfony-fly-starter
Top comments (1)
Thanks for sharing! very useful !!