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.)
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.
command: r
in docker-compose.yml.#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.
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.
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