I want to pass the startup command to postgres with docker-compose.

Introduction

If there is a command you want docker-compose to execute to start the container, write it in command:. However, the official image postgreSQL container does not start the essential postgre (DB) when the command is executed that way. I was really into it and spent about 2 days. (I would appreciate it if you could let me know in the comments if there is a better way or if this works.)

ENTRY POINT and CMD trap

Before going to docker-compose, about dockerfile, I think that you often set ENTRY POINT and CMD in dockerfile. I will omit the details of ENTRY POINT and CMD, but in a nutshell

1.ENTRY POINT is always executed when the container is started.
2.CMD is an argument if ENTRY POINT is set
3.CMD can be executed as a command if ENTRY POINT is not set
4.CMD is docker-compose.Can be overwritten with yml command

This is the place. It's easy for those who say it, but I'll verify everything. (Actually, I am writing an article to check if my understanding is wrong.)

mkdir test
cd test
touch Dockerfile
touch docker-compose.yml

Create a test directory like this and prepare two files, Dockerfile and docker-compose.yml. Describe to create an nginx container appropriately.

#Below is the contents of the Dockerfile
FROM nginx
RUN apt update && apt install -y procps
ENTRYPOINT [ "ps"]

docker-compose.yml


version: '3'
services:
  nginx:
    build: .
    tty: true
$ docker-compose up
nginx_1  |   PID TTY          TIME CMD
nginx_1  |     1 pts/0    00:00:00 ps

You can see that the result of the ps command is returned like this. Let's set CMD in the Dockerfile.

#Below is the contents of the Dockerfile
FROM nginx
RUN apt update && apt install -y procps
ENTRYPOINT [ "ps"]
CMD ["ax"]

Since the previous container was closed and the Dockerfile was updated, the nginx image created earlier is also deleted.

$ docker-compose down
$ docker rmi -f image ID
$ docker-compose up
nginx_1  |   PID TTY      STAT   TIME COMMAND
nginx_1  |     1 pts/0    Rs+    0:00 ps ax

Now you can see that the COMMAND part is ps ax and you can pass ax as an argument. Next, try to overwrite the CMD of Dockerfile with the command of docker-compose.yml.

docker-compose.yml


version: '3'
services:
  nginx:
    build: .
    tty: true
    command: r
$ docker-compose up
nginx_1  |   PID TTY      STAT   TIME COMMAND
nginx_1  |     1 pts/0    Rs+    0:00 ps r

The option could be overwritten with r.

Finally, when only CMD is specified and there is no ENTRY POIN.

#Below is the contents of the Dockerfile
FROM nginx
RUN apt update && apt install -y procps
CMD ["ps"]
$ docker-compose up
nginx_1  |   PID TTY          TIME CMD
nginx_1  |     1 pts/0    00:00:00 ps

Well, this is as expected. Of course, you can overwrite it with docker-compose.yml even if you only use CMD. You can check all the edges with the inspect command, so you can immediately see if it has been overwritten or if the ENTRY POINT has been set.

Main subject

The introduction has become longer, but it is reflected in the main subject. There is such a Dockerfile and docker-compose.yml.

#Below is the contents of the Dockerfile
FROM postgres
RUN apt update && apt install -y procps

docker-compose.yml


version: '3'
services:
  db:
    build: .
    tty: true
    environment:
      POSTGRES_PASSWORD: tekitou_koreiruyo
$ docker-compose up -d
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
0ca675fda6e3        test_db             "docker-entrypoint.s…"   29 seconds ago      Up 28 seconds       5432/tcp                 test_db_1

it is a good feeling. Go inside the container and use the ps command to check if db is running.

# ps ax
PID TTY      STAT   TIME COMMAND
    1 pts/0    Ss+    0:00 postgres
   65 ?        Ss     0:00 postgres: checkpointer
   66 ?        Ss     0:00 postgres: background writer
   67 ?        Ss     0:00 postgres: walwriter
   68 ?        Ss     0:00 postgres: autovacuum launcher
   69 ?        Ss     0:00 postgres: stats collector
   70 ?        Ss     0:00 postgres: logical replication launcher
   81 pts/1    Ss     0:00 bash
   87 pts/1    R+     0:00 ps ax

It's good It would be nice to be able to execute SQL when the container starts. You can create users automatically, add passwords, and more.

Execute the following command in the container.

psql -U postgres --command='CREATE DATABASE test'
>>CREATE DATABASE

You can connect to the DB and issue SQL by passing your favorite SQL statement in the --command part. Then psql -U postgres --command ='CREATE DATABASE test' You can pass this with CMD of Dockerfile orcommand:of docker-compose.yml, but that alone does not work. ..

Because if you look at the postgres container you created earlier with inspect

{
    "Cmd": [
      "postgres"
    ],
    "Entrypoint": [
      "docker-entrypoint.sh"
    ],
}

Because there is such a description. (The above json omits the contents considerably.) In other words, this is set from the beginning to pass the argument (CMD) to ENTRYPOIN explained at the beginning.

In this state, even if you simply add to command: in docker-compose.yml, it will only be recognized as an argument of ENTRYPOINT and an error will occur. In other words, by default, the command docker-entrypoint.sh postgres will run when the container is executed. So in addition to that, psql -U postgres --command ='CREATE DATABASE test' How can I run this command at container runtime? Place sh and sql in docker-entrypoint-initdb.d in the container. Sh and sql stored in this directory will be executed automatically when the container is started.

In this case, it seems good to just place the CREATE DATABASE test part as a .sql file directly under docker-entrypoint-initdb.d in the container. Create create_table.sql in the same directory as Dockerfile and docker-compose.yml. Then modify the Dockerfile to look like the one below.

FROM postgres
RUN apt update && apt install -y procps
COPY *.sql /docker-entrypoint-initdb.d/

I used a wildcard to specify the sql file, but this time I made it create_table.sql, so I can specify it with the file name as usual. Now run docker-compose up -d

Enter the docker exec -it container ID bash container and enter the DB with psql -U postgres.

postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 | 
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 test      | postgres | UTF8     | en_US.utf8 | en_US.utf8 | 
(4 rows)

You can see that there is a database named test at the bottom.

Now you can run your favorite sh or sql at startup even if ENTRY POINT is specified in the official image.

Summary

I wrote in command: psql -U postgres --command ='CREATE DATABASE test' in docker-compose.yml and lamented that it didn't work, but it doesn't work because I passed it as an argument of ENTRYPOINT. .. If you know how to write in docker-compose.yml, please let me know in the comments.

Recommended Posts

I want to pass the startup command to postgres with docker-compose.
I want to dark mode with the SWT app
I want to docker-compose up Next.js!
I want to distinct the duplicated data with has_many through
I want to return to the previous screen with kotlin and java!
[Java] I want to perform distinct with the key in the object
I want to use DBViewer with Eclipse 2018-12! !!
I want to pass the argument of Annotation and the argument of the calling method to aspect
I want to introduce the committee with Rails without getting too dirty
I want to test Action Cable with RSpec test
[For beginners] I want to automatically enter pre-registered data in the input form with a selection command.
I tried to link grafana and postgres [docker-compose]
I want to use java8 forEach with index
I want to var_dump the contents of the intent
I want to pass APP_HOME to logback in Gradle
pass two arguments to the URI with link_to
I want to play with Firestore from Rails
I want to truncate after the decimal point
I want to reduce simple mistakes. To command yourself.
I want to perform aggregation processing with spring-batch
[Rails] I want to load CSS with webpacker
I want to get the value in Ruby
I want to control the start / stop of servers and databases with Alexa
[Eclipse] I want to use the completion function, but I want to manage to confirm the completion with spaces.
I wanted to start the AP server and debug with just the Maven command
[Java] I want to calculate the difference from the date
I want to embed any TraceId in the log
I started MySQL 5.7 with docker-compose and tried to connect
I want to judge the range using the monthly degree
I want to know the answer of the rock-paper-scissors app
I want to display the name of the poster of the comment
I want to authenticate users to Rails with Devise + OmniAuth
I want to transition screens with kotlin and java!
I want to call the main method using reflection
You can't (yet) pass arguments to buildkit with docker-compose
[Rough commentary] I want to marry the pluck method
I want to be aware of the contents of variables!
I want to return the scroll position of UITableView!
I want to redirect sound from Ubuntu with xrdp
I want to simplify the log output on Android
I want to add a delete function to the comment function
I want to change the path after new registration after logging in with multiple devises.
Use the --build-arg option of docker-compose to pass environment variables to the container built with Dockerfile
I want to hit the API with Rails on multiple docker-composes set up locally
I want to fetch another association of the parent model from the intermediate table with has_many
Why can I use the rails command installed with gem? ??
[Beginner] I want to modify the migration file-How to use rollback-
The story that led to solving the error because postgres did not start with docker-compose up
I want to set the conditions to be displayed in collection_check_boxes
I tried to increase the processing speed with spiritual engineering
I want to use screen sharing on the login screen on Ubuntu 18
I want to convert characters ...
(´-`) .. oO (I want to easily find the standard output "Hello".
After posting an article with Rails Simple Calendar, I want to reflect it in the calendar.
I want to push an app made with Rails 6 to GitHub
I want to use Java Applet easily on the command line without using an IDE
I want to expand the clickable part of the link_to method
I want to change the log output settings of UtilLoggingJdbcLogger
I want to make a list with kotlin and java!
I want to call a method and count the number
I want to make a function with kotlin and java!