Docker Compose构建前创建外部目录及环境变量配置问题
解决方案
一、自动创建宿主机目录 /store/pg12/data
Docker Compose本身无法直接执行宿主机的shell命令,但可以通过两种方式实现自动创建目录,无需手动敲CLI:
方案1:用临时初始化容器
新增一个一次性服务,挂载宿主机的/store目录,在容器内执行创建命令(挂载后容器内操作对应宿主机路径):
version: '3.3' services: init_datadir: image: alpine:latest command: mkdir -p /store/pg12/data volumes: - /store:/store restart: "no" # 执行完就退出,无需长期运行 postgres12: container_name: pg12_1212 image: postgres:12 restart: unless-stopped ports: - "1212:5432" environment: - POSTGRES_DB=appdata - POSTGRES_USER=appadmin - POSTGRES_PASSWORD=12345678 - APP_DATA_DIR=/var/lib/postgresql/data # 容器内的环境变量 volumes: # 直接绑定宿主机目录替代原volume配置(原tmpfs配置会导致数据不持久化) - /store/pg12/data:/var/lib/postgresql/data - ./datastore/setup.sql:/docker-entrypoint-initdb.d/1.sql - ./datastore/schema.sql:/docker-entrypoint-initdb.d/2.sql - ./datastore/data.sql:/docker-entrypoint-initdb.d/3.sql depends_on: - init_datadir # 确保目录创建完成再启动postgres
注意:你原配置里的
tmpfs类型volume和device: /store/pg12/data是冲突的——tmpfs是内存临时文件系统,容器重启后数据会丢失。如果要持久化数据到宿主机,直接用宿主机路径:容器内路径的绑定挂载即可。
方案2:利用Docker自动创建目录+权限修复
直接用绑定挂载的话,Docker会自动创建不存在的宿主机目录,但默认权限是root:root,而postgres容器用postgres用户(UID=999)运行,会无法写入。可以通过修改启动命令来修复权限:
version: '3.3' services: postgres12: container_name: pg12_1212 image: postgres:12 restart: unless-stopped ports: - "1212:5432" environment: - POSTGRES_DB=appdata - POSTGRES_USER=appadmin - POSTGRES_PASSWORD=12345678 - APP_DATA_DIR=/var/lib/postgresql/data user: root # 先以root启动调整权限 command: bash -c "chown -R postgres:postgres /var/lib/postgresql/data && exec su postgres -c '/usr/local/bin/docker-entrypoint.sh postgres'" volumes: - /store/pg12/data:/var/lib/postgresql/data - ./datastore/setup.sql:/docker-entrypoint-initdb.d/1.sql - ./datastore/schema.sql:/docker-entrypoint-initdb.d/2.sql - ./datastore/data.sql:/docker-entrypoint-initdb.d/3.sql
这种方式不需要额外容器,Docker自动创建目录后,启动时先修改权限再正常运行postgres。
二、设置 APP_DATA_DIR 变量
容器内使用该变量
直接在postgres服务的environment字段添加即可,如上面示例中的- APP_DATA_DIR=/var/lib/postgresql/data,容器内的脚本或程序可以通过$APP_DATA_DIR访问。
传递宿主机的环境变量到容器
如果APP_DATA_DIR是宿主机已有的环境变量,想让容器继承,用下面的写法:
environment: - APP_DATA_DIR=${APP_DATA_DIR}
关于Dockerfile的必要性
完全不需要复杂的Dockerfile,上述Docker Compose配置就能解决问题。只有当你需要自定义镜像的基础镜像、预装软件等场景时,才需要编写Dockerfile,这类目录创建和环境变量配置的需求,用Compose就能搞定。
内容的提问来源于stack exchange,提问作者Andrzej Więcławski
相关产品推荐
相关产品推荐

