Docker - 无法通过脚本删除容器内的文件

Posted

技术标签:

【中文标题】Docker - 无法通过脚本删除容器内的文件【英文标题】:Docker - Cannot delete files inside container via script 【发布时间】:2021-10-10 11:04:19 【问题描述】:

在这个 Postgres Docker 映像上,我复制了几个文件来配置容器。

(1) init.sh - 复制到 Docker 入口点 (2) data.txt - 包含敏感信息

在 init.sh 结束时我想删除 data.txt,但文件永远不会被删除。

docker-compose.yml

version: '3.6'

services:
  postgres_test:
    container_name: postgres_13_3
    image: postgres_13_3
    restart: unless-stopped
    build:
      context: ./postgres
      dockerfile: postgres_13_test.dk
    environment:
        POSTGRES_PASSWORD: 'test'

postgres_13_test.dk

FROM postgres:13.3-alpine3.14

# copy files over
COPY ./data.txt /tmp/data.txt
RUN chmod 777 /tmp/data.txt
COPY ./init.sh /docker-entrypoint-initdb.d/init.sh

init.sh

# ... do other things first

# then in the end, delete file
rm -rf /tmp/data.txt     # <-- file never gets deleted

我错过了什么?

更新

现在用 --no-cache 重建容器 fesh,现在它显示此错误消息

postgres_13_3  | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init.sh
postgres_13_3  | rm: can't remove '/tmp/data.txt': Operation not permitted

我怎样才能防止这个错误?

【问题讨论】:

你确定你的入口点设置正确并且脚本正在执行吗? @Elia 是的,脚本正在执行。它正在创建数据库用户和表,它们都在那里。我在示例代码中省略了它。 我假设通过 dockerfile 复制文件是由 root 用户执行的,但 init.sh 是由 postgress 用户运行的,这就是你没有权限删除它的原因 【参考方案1】:

如果你检查它的docker-entrypoint.sh,你会发现脚本/docker-entrypoint-initdb.d/*在第一次建立数据库时只执行一次,这就是为什么你后来看到你的init.sh没有被执行。

设置新容器后,脚本有机会执行,但您会看到权限问题,这是因为init.sh 将使用postgres 用户执行,而不是root 用户,请参阅this:

if [ "$(id -u)" = '0' ]; then
        # then restart script as postgres user
        exec su-exec postgres "$BASH_SOURCE" "$@"
fi

另外,如果你查看/tmp的权限,你可以看到它的权限是:

ls -alh /tmp
total 8K
drwxrwxrwt    1 root     root        4.0K Aug  7 15:16 .
drwxr-xr-x    1 root     root        4.0K Aug  7 15:25 ..
-rwxrwxrwx    1 root     root           0 Aug  7 15:01 data.txt

这里,tsticky bit,这意味着如果用户postgresroot 不在同一个linux 组中,您将无法删除文件,尽管您仍然拥有w/tmp 权限.这就是即使您将data.txt 的权限更改为777 也无法删除data.txt 的原因。

因此,对您而言,解决方案是将 data.txt 的所有权更改为 postgres 的某些内容,并使用 chown 如下所示:

Dockerfile:

FROM postgres:13.3-alpine3.14

COPY ./data.txt /tmp/data.txt
RUN chmod 777 /tmp/data.txt
RUN chown postgres:postgres /tmp/data.txt
COPY ./init.sh /docker-entrypoint-initdb.d/init.sh

或者,不要将data.txt复制到/tmp,只需设置一个新文件夹,如/tmp2,将其权限更改为777,然后将data.txt复制到/tmp2

【讨论】:

以上是关于Docker - 无法通过脚本删除容器内的文件的主要内容,如果未能解决你的问题,请参考以下文章

无法连接到 Docker 容器内的 MongoDB

docker容器内的mysql说“无法通过套接字'/var/run/mysqld/mysqld.sock'连接到本地MySQL服务器”

无法访问 docker 容器内的烧瓶应用程序

通过php访问docker容器内的文件

Docker Volume

如何在 Docker 容器内的 CockroachDB 中运行 SQL 脚本?