Introduction
Imagine you have your Symfony project ready and working and you want other technicians and developers to be able to install and use it easily so that they can give you some feedback and advice.
Installing a Symfony project can involve many tasks such as:
- Install composer.
- Install vendors using composer.
- Install assets using node and npm.
- Setup a database using doctrine.
- Install the Symfony-cli tool to start a local development server.
To avoid doing all the above staff, you can build your own docker image for your project and encapsulate those tasks on it. This way, your project would only require to have docker installed.
Obviously, you could also deploy your app to some cloud but this way can also be useful if you do not want to deploy it yet.
Two things before starting:
1.- This image does not create a new user for the container so it starts as root. This is not suitable for production environments for security reasons, but is sufficient for a local environment.
2.- This image does not create an SSL certifcate for the nginx vhost. If you would like me to add such feature, let me know in the comments.
Creating the image
I'm going to base this on the image from my example project that you can find stored in my github account.
Installing essential packages
FROM ubuntu:latest
# Set non-interactive mode for apt
ARG DEBIAN_FRONTEND=noninteractive
# Update and install required packages in a single RUN command
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y \
apt-utils \
locales \
software-properties-common \
nginx \
sqlite \
curl \
git
- Start from the image of the latest version of Ubuntu.
- Set the variable DEBIAN_FRONTEND to the value noninteractive so that user interactions are not requested when executing some commands.
- Install the first dependencies that we could need
Installing PHP dependencies and setting the language configuration
RUN add-apt-repository ppa:ondrej/php
RUN apt-get update && \
apt-get install -y \
php8.2 \
php8.2-fpm \
php8.2-xml \
php8.2-mbstring \
php8.2-curl \
php8.2-gmp \
php8.2-gd \
php8.2-sqlite3 \
php8.2-bcmath
RUN apt-get clean
# Set the locale
RUN locale-gen es_ES.UTF-8
ENV LC_ALL es_ES.UTF-8
# Set working directory
WORKDIR /var/www/crypto-bills-dapp
# Copy application files
COPY . .
- Install PHP dependencies.
- Clean the packages cache.
- Set the language configuration for the container.
- Set the working directory.
- Copy the contents to the working directory.
Installing Node and composer
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Install Node.js using NVM
ENV NODE_VERSION=20.0.0
ENV NVM_DIR=/root/.nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash && \
. "$NVM_DIR/nvm.sh" && \
nvm install ${NODE_VERSION} && \
nvm alias default v${NODE_VERSION} && \
ln -s "$NVM_DIR/versions/node/v${NODE_VERSION}/bin/node" /usr/local/bin/node && \
ln -s "$NVM_DIR/versions/node/v${NODE_VERSION}/bin/npm" /usr/local/bin/npm
# Verify Node.js and npm installation
RUN node --version && npm --version
- Install composer so that we can install the symfony vendors later.
- Download and install node using the nvm package manager.
- Install the node version we've specified within the NODE_VERSION variable and move the node and npm binaries to the /usr/local/bin folder.
- Verify node and npm installation.
Install Symfony vendors, setup the database and install assets
# Install PHP dependencies
ENV COMPOSER_ALLOW_SUPERUSER=1
RUN composer install && \
bin/console cache:clear && \
bin/console doctrine:schema:drop --force && \
bin/console doctrine:schema:create && \
bin/console app:setup
# Install Node.js dependencies
RUN npm install && npm run dev
- Install project dependencies with composer. We use COMPOSER_ALLOW_SUPERUSER to allow running composer in root mode.
- Clear Symfony cache (it would not be necessary since composer install do it after the vendors installation).
- Create the database schema using doctrine.
- The app:setup command is a specific command to my project that performs some tasks so that the app can work, such as deploying the contract with which the app interacts.
- Install node dependencies and run the npm run dev command to compile the assets and publish them.
Installing and running nginx
# Configure Nginx
RUN rm /etc/nginx/sites-enabled/default && \
cp nginx/vhost.conf /etc/nginx/sites-available/ && \
ln -s /etc/nginx/sites-available/vhost.conf /etc/nginx/sites-enabled/vhost.conf
# Set permissions
RUN chmod -R 777 var/
# Define default command
CMD service php8.2-fpm start && nginx -g 'daemon off;'
# Expose ports
EXPOSE 80
-
Move the file that contains the virtual-host config to the nginx sites-available folder.
You can find that file on the nginx folder on the github project.
Create a symbolic link from the vhost file to the sites-enabled folder so that nginx starts it.
Give full permissions to the /var folder so that the webserver user can write on it.
Start php-fpm and nginx in non-daemon mode.
Expose port 80 which is where nginx keeps listening.
Building the image and starting the container
Now, we are ready to build the image and run the container. We can achieve it by using the following commands:
docker build --no-cache -t crypto-bills .
docker run -it -p 97:80 crypto-bills
After the container is started, if you navigate to the *http://localhost:97 url you should see the login page:
Conclusion
This is the way I usually do when I want other developers to see my job, not only the code but the app working. I hope it can be useful for you and, if you know a better way for achieving that, please let me know in the comments :).
If you like my content and enjoy reading it, consider giving an chance to my last book: Building an Operation-Oriented Api using PHP and The Symfony Framework.
Top comments (0)