DEV Community

Burhanuddin Ahmed
Burhanuddin Ahmed

Posted on • Edited on

Chapter 3: Dokerize Laravel App with Nginx and Postgres.

Postgres SQL

It's time to set up our database in Docker. Because the app is relatively small and built on monolith architecture, so we will install it inside Docker.

Now we can go to our /infra/pgsql and add a new folder named script and then create initdb.sh inside it.

Initdb.sh will be used to create a script to create PG user and PG databases. In this case, my app is using two databases within the same DB instace.

So we first, create a function to create the user, database, and privilege. Then we can loop it over the number of databases we want to create.

initdb.sh

#!/bin/bash

set -e
set -u

function create_user_and_db() {
  local database=$1

    echo "  Creating user and database '$database'"
    psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
        CREATE USER $database;
        CREATE DATABASE $database;
        GRANT ALL PRIVILEGES ON DATABASE $database TO $database;
EOSQL
}

if [ -n "$POSTGRES_MULTIPLE_DATABASES" ]; then
    echo "Multiple database creation requested: $POSTGRES_MULTIPLE_DATABASES"
    for db in $(echo $POSTGRES_MULTIPLE_DATABASES | tr ',' ' '); do
        create_user_and_db $db
    done
    echo "Multiple databases created"
fi
Enter fullscreen mode Exit fullscreen mode

If you want to see a different way to install PG in Docker, you can check here.

Inside pgsql folder, we can create a Dockerfile

FROM postgres:14.1
COPY script/initdb.sh /docker-entrypoint-initdb.d/
Enter fullscreen mode Exit fullscreen mode

The initdb.sh will be copied to docker-entrypoint-initdb.d, so it will automatically run when we run docker-compose.

So after we have added all of those items, here is the complete docker-compose.yml

version: "3.7"

networks:
  app-network:
    driver: bridge

services: 
  app:
    container_name: app
    build:
      context: ./infra/app
      dockerfile: Dockerfile
    image: php-laravel-7.0
    restart: unless-stopped
    tty: true
    working_dir: /var/www
    volumes: 
      - ./:/var/www
    networks: 
      - app-network

  db:
    container_name: pgsql
    build:
      context: ./infra/pgsql
      dockerfile: Dockerfile
    image: pgsql-docker
    restart: unless-stopped
    expose:
     - "5432"
    ports:
      - "5433:5432"
    volumes: 
      - ./infra/pgsql/script:/docker-entrypoint-initdb.d
      - ./infra/pgsql/data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=${DB_USERNAME}
      - POSTGRES_MULTIPLE_DATABASES=main_db,logger_db // you change this
    networks:
      - app-network

  nginx:
    image: nginx:1.19.8-alpine
    container_name: nginx
    restart: unless-stopped
    tty: true
    ports: 
        - 8100:80
    volumes: 
        - ./:/var/www
        - ./infra/nginx/conf:/etc/nginx/conf.d
    networks: 
        - app-network
Enter fullscreen mode Exit fullscreen mode

Now we can run docker-compose build then docker-compose up -d, if we don't see any error, so we can assume our docker set up is a success.

We are still not finished yet because we did manual DB migration, yes we didn't use Laravel migration.

We need to dump the DB manually like this. You can adjust the db dump path.

docker-compose exec -T db pg_restore -U postgres -d main_db < db_dump/dump-<DB NAME>-202203201444.sql
Enter fullscreen mode Exit fullscreen mode

Because we are using
- ./infra/pgsql/data:/var/lib/postgresql/data in our docker-compose, so we expect our database data to be persisted even if the docker is shut down.

One more thing, we need to run these two script to make our Laravel app working.

docker-compose exec -T app php artisan key:generate
Enter fullscreen mode Exit fullscreen mode
docker-compose exec -T app composer install
Enter fullscreen mode Exit fullscreen mode

If we want to run laravel db migration instead, we can run this command.

docker-compose exec -T app php artisan migrate
Enter fullscreen mode Exit fullscreen mode

That's all from my post.

Top comments (0)