Search code examples
postgresqldockerdocker-compose

bash short circuiting not working in docker compose command directive


I'm creating a postgres container and after db service is healthy I run psql service which simply creates database if it doesn't exist.

Now in psql service command directive, I expect the left side of OR operator to exit with non zero code and then the right side of the command should be executed. This is exactly what happens if I run the command directly inside postgres image. But here in docker compose file, short circuit doesn't work. When the left side exits with non zero code, it doesn't execute right side.

I'm aware that POSTGRES_DB env var can be passed to postgres service, but I've to create the database this way. I've already tried running this command with sh -c "COMMAND HERE"

Docker version 27.3.1

Any help appreciated. Thanks!

  psql:
    image: alpine/psql:16.3
    depends_on:
      db:
        condition: service_healthy
    environment:
      - PGPASSWORD=password
    #https://stackoverflow.com/a/59617496/18954618
    command: psql -h db -U postgres -c 'select 1' -d 'my_db' &> /dev/null || psql -d 'postgres' -h db -U postgres -tc 'create database my_db'

  db:
    container_name: postgres
    image: postgres:13.18
    restart: unless-stopped
    expose:
      - 5432
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: postgres
    volumes:
      - ./volumes/pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

Solution

  • Updated!!!

    I think your problem is discussed here:

    docker-compose use pipe in command

    so basically docker-compose has problem with pipes - ||

    version: '3.9'
    
    services:
      psql:
        image: alpine/psql:16.3
        depends_on:
          db:
            condition: service_healthy
        environment:
          - PGPASSWORD=password
        entrypoint: sh -c 'psql -h db -U postgres -c "select 1" -d my_db &> /dev/null || psql -d postgres -h db -U postgres -tc "create database my_db"'
    
      db:
        container_name: postgres
        image: postgres:13.18
        restart: unless-stopped
        expose:
          - 5432
        environment:
          POSTGRES_PASSWORD: password
          POSTGRES_USER: postgres
        volumes:
          - ./volumes/pgdata:/var/lib/postgresql/data
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U postgres"]
          interval: 5s
          timeout: 5s
          retries: 5