Linux 如何向容器发送命令以在不运行容器的情况下更改文件?

Linux 如何向容器发送命令以在不运行容器的情况下更改文件?,linux,bash,docker,shell,containers,Linux,Bash,Docker,Shell,Containers,我有一个容器Postgres,它在Dockerfile中启动一个docker entrypoint.sh,在这个shell文件中有一个命令,我想使用这个命令删除它: sed -i 's/exec "$@"//g' docker-entrypoint.sh docker run -v $(pwd):/docker-entrypoint-initdb.d -e POSTGRES_PASSWORD=password \ --entrypoint="docker

我有一个容器
Postgres
,它在Dockerfile中启动一个
docker entrypoint.sh
,在这个shell文件中有一个命令,我想使用这个命令删除它:

sed -i 's/exec "$@"//g' docker-entrypoint.sh
docker run -v $(pwd):/docker-entrypoint-initdb.d -e POSTGRES_PASSWORD=password \
     --entrypoint="docker-entrypoint-initdb.d/docker-entrypoint-custom.sh" postgres postgres
目标是能够使用修改后的docker-entrypoint.sh运行容器(不使用exec“@”)

如何在之前启动该命令的情况下运行容器? 我使用了另一种方法,在该方法中,我使用另一个不带“exec”@“的shell文件覆盖docker-entrypoint.sh,然后使用以下命令装载它以运行我的容器:

sed -i 's/exec "$@"//g' docker-entrypoint.sh
docker run -v $(pwd):/docker-entrypoint-initdb.d -e POSTGRES_PASSWORD=password \
     --entrypoint="docker-entrypoint-initdb.d/docker-entrypoint-custom.sh" postgres postgres
我确信有一种更好的方法,在bash中运行命令,然后运行自己的命令

我尝试过类似的方法,但不起作用:

docker run --rm -v $PWD:/docker-entrypoint-initdb.d -e POSTGRES_PASSWORD=password  --entrypoint=/bin/bash postgres sed -i 's/exec "$@"//g' docker-entrypoint.sh &&  postgres docker-entrypoint.sh
我使用了另一种方法,使用另一个不带“exec”@“的shell文件覆盖docker-entrypoint.sh

好的,你正在挂载一个完整的目录,你有一个入口点的副本。只需挂载一个文件,并在文件中进行修改

# docker-entrypoint-custom.sh
#!/bin/sh
# do the modification
sed -i 's/exec "$@"//g' /docker-entrypoint.sh
# Just run it
/docker-entrypoint.sh "$@"

另一种方法是使用修改的入口点构建另一个容器

# Dockefile....
FROM postgres
RUN sed -i 's/exec "$@"//g' /docker-entrypoint.sh
我使用了另一种方法,使用另一个不带“exec”@“的shell文件覆盖docker-entrypoint.sh

好的,你正在挂载一个完整的目录,你有一个入口点的副本。只需挂载一个文件,并在文件中进行修改

# docker-entrypoint-custom.sh
#!/bin/sh
# do the modification
sed -i 's/exec "$@"//g' /docker-entrypoint.sh
# Just run it
/docker-entrypoint.sh "$@"

另一种方法是使用修改的入口点构建另一个容器

# Dockefile....
FROM postgres
RUN sed -i 's/exec "$@"//g' /docker-entrypoint.sh

postgres
图像的默认操作是运行
postgres
。如果您想让它运行其他命令,只需将该命令放在
docker run
命令的末尾即可。不要担心编辑入口点脚本

出于调试的目的,一件非常典型的事情是启动一个交互式shell,而不是正常的服务器进程;然后,您可以查看创建的文件系统,看看发生了什么

docker run --rm -it \
  -v $PWD:/docker-entrypoint-initdb.d \
  -e POSTGRES_PASSWORD=password \
  postgres \
  /bin/bash
这里到底发生了什么?如果您查看,您会注意到它同时包含一个
入口点和一个
CMD

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]
当你两样东西都有的时候。
exec“$@”
行将入口点脚本替换为另一个由位置参数组成的命令;也就是说,它将
docker entrypoint.sh
替换为
postgres
。在命令行中重写
CMD
很容易,正如我在上面所做的那样,但是替换
ENTRYPOINT
更为棘手

这就形成了一种通用模式,即使用
ENTRYPOINT
进行首次初始化,然后使用
exec“$@”
运行
CMD

#/垃圾箱/垃圾箱
#我是docker-entrypoint.sh
#以Dockerfile的形式调用我(必须使用JSON数组语法)
#入口点[“/path/to/ENTRYPOINT.sh”]
#执行启动时初始化,如创建数据库或
#为主进程设置环境变量
...
#然后启动CMD
执行官“$@”

postgres图像的默认操作是运行
postgres
。如果您想让它运行其他命令,只需将该命令放在
docker run
命令的末尾即可。不要担心编辑入口点脚本

出于调试的目的,一件非常典型的事情是启动一个交互式shell,而不是正常的服务器进程;然后,您可以查看创建的文件系统,看看发生了什么

docker run --rm -it \
  -v $PWD:/docker-entrypoint-initdb.d \
  -e POSTGRES_PASSWORD=password \
  postgres \
  /bin/bash
这里到底发生了什么?如果您查看,您会注意到它同时包含一个
入口点和一个
CMD

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]
当你两样东西都有的时候。
exec“$@”
行将入口点脚本替换为另一个由位置参数组成的命令;也就是说,它将
docker entrypoint.sh
替换为
postgres
。在命令行中重写
CMD
很容易,正如我在上面所做的那样,但是替换
ENTRYPOINT
更为棘手

这就形成了一种通用模式,即使用
ENTRYPOINT
进行首次初始化,然后使用
exec“$@”
运行
CMD

#/垃圾箱/垃圾箱
#我是docker-entrypoint.sh
#以Dockerfile的形式调用我(必须使用JSON数组语法)
#入口点[“/path/to/ENTRYPOINT.sh”]
#执行启动时初始化,如创建数据库或
#为主进程设置环境变量
...
#然后启动CMD
执行官“$@”

您当前使用的方法是iMO此处选项中最好的。您将单引号与
sed
命令一起使用,并在其中使用
$@
变量。注意,单引号内的任何变量都不会被插值。请使用双引号。@P
exec“$@”
可能是OP想要替换的,也就是说,按原样,不需要任何替换。您当前使用的方法是iMO这里的选项中最好的。您使用带有
sed
命令的单引号,并在其中使用
$@
变量。注意,单引号内的任何变量都不会被插值。请使用双引号。@P
exec“$@”
可能是OP想要替换的东西,即原样,没有任何替换。这太干净了!谢谢你,它成功了!这太干净了!谢谢你,它成功了!谢谢你的解释@David,但我的目标是从我的主shell文件中删除“exec”@!一旦你有了它,你会做什么?如果您只想让容器在卷中设置初始数据库并运行初始化脚本,可以将命令设置为类似于
/bin/true
,其最终效果与删除行相同。目标是使用此容器运行架构测试/bin/true会取代/bin/sh吗?(我不知道)如果你
docker运行。。。postgres/bin/true
它将启动entrypoint脚本。当它到达e