Docker for Dummies - Creating Your First Full-Stack Environment

Published by Azat Akmyradov

Hey there, future Docker whizzes! Today, we're diving into the Docker deep end, but don't worry – we're gonna keep things light, breezy, and beginner-friendly. We're going to cook up a full-stack setup using Docker. You ready? Let's get started!

Saucing Up Our Docker-Compose

Our adventure begins with the Docker Compose file. This is where we lay out our plan, like a blueprint for a house. Here, we're building a full-stack application with nginx, mysql, php, composer, node, and redis.

docker-compose.yml

version: '3.8' services: nginx: build: context: . dockerfile: nginx.dockerfile volumes: - ./src:/var/www/html ports: - 80:80 depends_on: - mysql - php - redis mysql: image: mariadb:10.6 expose: - 3306:3306 environment: MYSQL_DATABASE: laravel MYSQL_USER: laravel MYSQL_PASSWORD: secret MYSQL_ROOT_PASSWORD: secret volumes: - ./mysql:/var/lib/mysql php: build: context: . dockerfile: php.dockerfile volumes: - ./src:/var/www/html composer: build: context: . dockerfile: composer.dockerfile volumes: - ./src:/var/www/html working_dir: /var/www/html node: build: context: . dockerfile: node.dockerfile volumes: - ./src:/var/www/html working_dir: /var/www/html redis: build: context: . dockerfile: redis.dockerfile volumes: - ./redis:/data ports: - 6379:6379

version is our Docker Compose version, and services is where we list all our ingredients. Each service represents a different part of our application.

Diving into Dockerfiles

Now, let's talk about Dockerfiles. These are the recipe cards for our ingredients. Each Dockerfile tells Docker how to build each part of our application.

The Nginx Dockerfile

FROM nginx:stable-alpine ENV NGINXUSER=laravel ENV NGINXGROUP=laravel RUN mkdir -p /var/www/html/public ADD nginx/default.conf /etc/nginx/conf.d/default.conf RUN sed -i "s/user www-data/user ${NGINXUSER}/g" /etc/nginx/nginx.conf RUN adduser -g ${NGINXGROUP} -s /bin/sh -D ${NGINXUSER}

Our Nginx Dockerfile starts by pulling in an existing image (nginx:stable-alpine). This is like buying a pre-made pizza base from the store. We then customize it by adding our user and group (both laravel), creating the necessary directory and adjusting the Nginx configuration.

The PHP Dockerfile

FROM php:8-fpm-alpine ENV PHPGROUP=laravel ENV PHPUSER=laravel RUN adduser -g ${PHPGROUP} -s /bin/sh -D ${PHPUSER} RUN sed -i "s/user = www-data/user = ${PHPUSER}/g" /usr/local/etc/php-fpm.d/www.conf RUN sed -i "s/group = www-data/group = ${PHPGROUP}/g" /usr/local/etc/php-fpm.d/www.conf RUN mkdir -p /var/www/html/public RUN docker-php-ext-install pdo pdo_mysql CMD [ "php-fpm", "-y", "/usr/local/etc/php-fpm.conf", "-R" ]

Our PHP Dockerfile is similar. We start with a pre-made PHP image (php:8-fpm-alpine), add our user and group, create the directory, and make sure PHP knows to use our user and group instead of the default www-data.

The Composer Dockerfile

FROM composer:lts ENV COMPOSER_USER=laravel ENV COMPOSER_GROUP=laravel RUN adduser -g ${COMPOSER_GROUP} -s /bin/sh -D ${COMPOSER_USER}

We follow the same pattern with Composer. We're starting with the composer:lts image, and then add our user and group.

The Redis Dockerfile

FROM redis/redis-stack:latest ENV REDIS_USER=laravel ENV REDIS_GROUP=laravel RUN groupadd ${REDIS_GROUP} && adduser --ingroup ${REDIS_GROUP} ${REDIS_USER}

For Redis, we start with the redis/redis-stack:latest image and then add our user and group.

The Node Dockerfile

FROM node:current-alpine ENV NODE_USER=laravel ENV NODE_GROUP=laravel RUN adduser -g ${NODE_GROUP} -s /bin/sh -D ${NODE_USER}

The Node Dockerfile follows the same pattern as the others. We start with the node:current-alpine image and add our user and group.

The Nginx Configuration File

This file tells Nginx how to handle requests. It includes details like which files to serve for a given request and how to handle PHP files.

Project Structure

Your project should look something like this:

- project-folder/ - docker-compose.yml - nginx.dockerfile - php.dockerfile - composer.dockerfile - redis.dockerfile - node.dockerfile - src/ - mysql/ - redis/ - nginx/ - default.conf

Starting the Services

In the same directory as your docker-compose.yml file, open your terminal or command line interface. To start all of your services, you simply need to type in this magical incantation:

docker-compose up -d

"Docker-compose up" tells Docker to start up all the services in your Docker Compose file. The "-d" flag is for "detached mode," which means Docker will run your services in the background.

Nginx should now be running and ready to serve your application. You can test this by going to http://localhost in your web browser. You should see your application up and running!

Using composer

Next, we need to get Composer to install our PHP dependencies. Docker makes this as easy as pie. In your terminal, type in:

docker-compose run --rm composer install

This tells Docker to run the composer install command, which installs your PHP dependencies. The "--rm" flag tells Docker to remove the container after the command has been executed.

Using NodeJS

Lastly, we need Node to install our JavaScript dependencies. This is just as easy:

docker-compose run --rm node npm install

And there you have it! A full-stack setup, cooked to perfection with Docker. Remember, like any good recipe, feel free to tweak this one to suit your taste. Happy Docker-ing!