在Docker中挂载Postgres卷。权限被拒绝。

10
我将尝试将主机上的文件夹映射到Postgres容器中,以便即使容器被销毁,我的数据也能得到保存。
首先,我创建了一个名为pg-data的新目录。

enter image description here

其次,我在docker-compose.yml中描述了容器。
version: '3.7'

networks:
  backend-network:
    driver: bridge
  frontend-network:
    driver: bridge

volumes:
   redis-data:
   pg-data:

services:
  &app-service app: &app-service-template
    container_name: k4fntr_app
    build:
      context: ./docker/php-fpm
      args:
        UID: ${UID?Use your user ID}
        GID: ${GID?Use your group ID}
        USER: ${USER?Use your user name}
    user: "${UID}:${GID}"
    hostname: *app-service
    volumes:
      - /etc/passwd/:/etc/passwd:ro
      - /etc/group/:/etc/group:ro
      - ./:/var/www/k4fntr
    environment:
      APP_ENV: "${APP_ENV}"
      CONTAINER_ROLE: app
      FPM_PORT: &php-fpm-port 9000
      FPM_USER: "${UID:-1000}"
      FPM_GROUP: "${GID:-1000}"
    depends_on:
      - redis
      - database
    networks:
      - backend-network

  &queue-service queue:
    <<: *app-service-template
    container_name: k4fntr_queue
    restart: always
    hostname: *queue-service
    depends_on:
      - app
    environment:
      CONTAINER_ROLE: queue

  &schedule-service schedule:
    <<: *app-service-template
    container_name: k4fntr_schedule
    restart: always
    hostname: *schedule-service
    depends_on:
      - app
    environment:
      CONTAINER_ROLE: scheduler

  &php-fpm-service php-fpm:
    <<: *app-service-template
    container_name: k4fntr_php-fpm
    user: 'root:root'
    restart: always
    hostname: *php-fpm-service
    ports: [*php-fpm-port]
    entrypoint: /fpm-entrypoint.sh
    command: php-fpm --nodaemonize -d "opcache.enable=0" -d "display_startup_errors=On" -d "display_errors=On" -d "error_reporting=E_ALL"
    networks:
      - backend-network
      - frontend-network

  mail:
    container_name: k4fntr_mail
    image: mailhog/mailhog
    ports:
    - "1025:1025"
    - "8025:8025"
      - backend-network

  database:
    container_name: k4fntr_database
    build: ./docker/postgres
    restart: always
    environment:
      ENV: ${APP_ENV}
      TESTING_DB: ${DB_DATABASE_TESTING}
      POSTGRES_DB: ${DB_DATABASE}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    ports:
      - "15432:5432"
    volumes:
      - ./docker/postgres/prod/:/prod
      - ./docker/postgres/pg-data:/var/lib/postgresql/data:Z
    networks:
      - backend-network

    - backend-network

  database:
    container_name: k4fntr_database
    build: ./docker/postgres
    restart: always
    environment:
      ENV: ${APP_ENV}
      TESTING_DB: ${DB_DATABASE_TESTING}
      POSTGRES_DB: ${DB_DATABASE}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    ports:
      - "15432:5432"
    volumes:
      - ./docker/postgres/prod/:/prod
      - ./docker/postgres/pg-data:/var/lib/postgresql/data:rw
    networks:
      - backend-network

    - backend-network

  nginx:
    container_name: k4fntr_nginx
    image: nginx
    volumes:
    - ./docker/nginx/config:/etc/nginx/conf.d
    - ./:/var/www/k4fntr
    depends_on:
      - *php-fpm-service
    ports:
      - "8084:80"
    networks:
      - frontend-network

  redis:
    container_name: k4fntr_redis
    image: redis
    restart: always
    command: redis-server
    volumes:
      - ./docker/redis/config/redis.conf:/usr/local/etc/redis/redis.conf
      - ./docker/redis/redis-data:/data:rw
    ports:
     - "16379:6379"
    networks:
      - backend-network

  database:
    container_name: k4fntr_database
    build: ./docker/postgres
    restart: always
    environment:
      ENV: ${APP_ENV}
      TESTING_DB: ${DB_DATABASE_TESTING}
      POSTGRES_DB: ${DB_DATABASE}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    ports:
      - "15432:5432"
    volumes:
      - ./docker/postgres/prod/:/prod
      - ./docker/postgres/pg-data:/var/lib/postgresql/data:Z
    networks:
      - backend-network

我还有一个 Dockerfile 存在于 docker/postgres/ 目录下,其中包含以下代码

    FROM postgres:10.5-alpine

    COPY /docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/

    RUN apk add openssh-client
    RUN chmod a+r /docker-entrypoint-initdb.d/*

    RUN mkdir /prod

    RUN chmod a+r /prod

然后我使用docker-compose exec -d --build构建我的镜像

完成后,我的用户更改为70:root

enter image description here

我无法在没有sudo权限的情况下对此文件夹进行任何操作。当我尝试重建容器时,也会出现错误。

/usr/local/bin/docker-compose up -d --build
Building database
Traceback (most recent call last):
  File "bin/docker-compose", line 6, in <module>
  File "compose/cli/main.py", line 72, in main
  File "compose/cli/main.py", line 128, in perform_command
  File "compose/cli/main.py", line 1077, in up
  File "compose/cli/main.py", line 1073, in up
  File "compose/project.py", line 548, in up
  File "compose/service.py", line 351, in ensure_image_exists
  File "compose/service.py", line 1106, in build
  File "site-packages/docker/api/build.py", line 160, in build
  File "site-packages/docker/utils/build.py", line 30, in tar
  File "site-packages/docker/utils/build.py", line 49, in exclude_paths
  File "site-packages/docker/utils/build.py", line 214, in rec_walk
  File "site-packages/docker/utils/build.py", line 184, in rec_walk
PermissionError: [Errno 13] Permission denied: '/home/ubuntu/PhpstormProjects/fntr/docker/postgres/pg-data'
[16332] Failed to execute script docker-compose

我需要删除这个文件夹(使用sudo),然后进行重建。
我尝试过:
1 - 我已经阅读了https://hub.docker.com/_/postgres的说明(任意--用户注释),并尝试在容器内卷积/etc/passwd,并使用用户:"${UID}:${GID}",但是出现了错误。
initdb: could not access directory "/var/lib/postgresql/data": permission denied

2 - 将PGDATA用于其他地方时,重建过程中出现了相同的错误。

3 - 在Dockerfile中创建/var/lib/postgresql/data并赋予777权限,但是postgres entrypoints从镜像中删除了此文件夹并重新创建了它。

我真的需要帮助解决这个问题,因为我已经花了3天时间还没有任何效果。


3
为了立即解决docker-compose up --build问题,请将pg-data目录添加到项目的.dockerignore文件中。有关此问题的讨论在github上进行。 - liberteh
3个回答

8

这是我在Manjaro Linux上的操作方法。

首先,我需要手动创建pgdata文件夹。如果我忽略了这一步骤,Docker会以错误的权限创建pgdata文件夹。

mkdir -p /some/path/pddata

接下来,我将使用 --user 参数创建 Docker 容器并映射我的用户:

docker container run -d --name=pg -p 5432:5432 --user $(id -u):$(id -g) -e POSTGRES_PASSWORD=postgres -e PGDATA=/pgdata -v /host/path/to/pgdata:/pgdata postgres:latest

经过许多测试和尝试,您的解决方案起作用了。谢谢。 - Amjad Hussain Syed

1
下面的方法适用于我,也许你需要从一个更简单的设置开始,并在朝向完整配置的过程中找出问题的原因:
version: '3.7'

volumes:
   pg-data:

services:
  database:
    image: postgres:latest
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      PGDATA: /pg-data
    ports:
      - "5432:5432"
    volumes:
      - pg-data:/pg-data


所以…
########################################
# start db
########################################
▶ docker-compose up -d
Creating docker-compose-pg_database_1 ... done

########################################
# note pg-data is created
########################################ls
docker-compose.yml pg-data

########################################
# create some data
########################################
▶ docker-compose exec database psql -U postgres
psql (12.2 (Debian 12.2-2.pgdg100+1))
Type "help" for help.

postgres=# create database foo;
CREATE DATABASE
postgres=# \q

########################################
# remove the container and any non-mounted data
########################################
▶ docker-compose rm -sf
Stopping docker-compose-pg_database_1 ... done
Going to remove docker-compose-pg_database_1
Removing docker-compose-pg_database_1 ... done

########################################
# start the container again
########################################
▶ docker-compose up -d
Creating docker-compose-pg_database_1 ... done

########################################
# see data from before
########################################
▶ docker-compose exec database psql -U postgres
psql (12.2 (Debian 12.2-2.pgdg100+1))
Type "help" for help.

postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 foo       | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 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
(4 rows)

0
尝试将Postgres的Docker卷中所有文件的所有权更改回由容器的postgres用户拥有。
docker compose run --rm --user root <service-name> chown -R postgres:postgres /home/postgres/pgdata/

或者

另一种方法是在容器中找到postgres用户的用户和组ID。

> docker compose exec timescale id -u
1000
> docker compose exec timescale id -g
1000

然后将文件的所有权从Docker主机更改为容器postgres用户所属的用户ID和组ID。
chown -R 1000:1000 /var/lib/docker/volumes/<postgres-data-volume-name>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接