[英]Deploying postgresql docker with ssl certificate and key with volumes
I'm trying to deploy a postgresql container.我正在尝试部署一个 postgresql 容器。 I'm trying to put ssl certificate and key in the container using volumes, but I can't get the permissions right.
我正在尝试使用卷将 ssl 证书和密钥放入容器中,但我无法获得正确的权限。 The files need to be readable by the container's
postgres
user, but also have limited permissions( 600
).这些文件需要容器的
postgres
用户可读,但也有有限的权限( 600
)。
Is it possible using volumes, or will I have to override the Dockerfile for this?是否可以使用卷,或者我是否必须为此覆盖 Dockerfile?
Thanks.谢谢。
It is possible to mount the key and certificate into the postgres container, and for postgres to use them from there. 可以将密钥和证书安装到postgres容器中,并让postgres从那里使用它们。 But you will have to face the issue with the owner and permissions of the
server.key
. 但是您将不得不面对
server.key
的所有者和权限的问题。
From the PostgreSQL Documentation on this subject : 从PostgreSQL文档中可以找到 :
On Unix systems, the permissions on server.key must disallow any access to world or group;
在Unix系统上,对server.key的许可必须禁止对world或group的任何访问。 achieve this by the command chmod 0600 server.key.
通过命令chmod 0600 server.key来实现。 Alternatively, the file can be owned by root and have group read access (that is, 0640 permissions).
或者,该文件可以由root拥有,并具有组读取访问权限(即0640权限)。
This means that you have to: 这意味着您必须:
server.key
file to either root
or postgres
. server.key
文件的所有者设置为root
或postgres
。 600
or 640
permissions on it. 600
或640
权限。 ( Update: It is implied here, that the group owner of the file, is a group that contains the postgres
user, like the default postgres
group) postgres
用户的组,例如默认的postgres
组) If you are working from a Windows host, you will have a hard time with this. 如果使用Windows主机,则将很难。 Because the permissions on any file in the volume that you map into the container will be
-rwxr-xr-x
( 755
), and the owner will be root
. 因为您映射到容器中的卷中任何文件的权限都是
-rwxr-xr-x
( 755
),而所有者将是root
。 And you will not be able to change this as long as the file is mounted from your windows volumes. 只要从Windows卷上挂载文件,您将无法更改此设置。 If you try using
chmod
on the file, it will just fail silently. 如果您尝试在文件上使用
chmod
,它将只会静默失败。
If you on the other hand are on a linux host, this can be done with minimum effort. 另一方面,如果您在linux主机上,则可以轻松完成此操作。 The permissions from the host system will be preserved into the image.
来自主机系统的权限将保留在映像中。 And the ownership will too, litterally.
所有权也将日渐减少。 By this I mean, that the numerical owner and group owner of the
server.key
will be preserved when they are volume mapped into the container. 我的意思是,将
server.key
的数字所有者和组所有者映射到容器后,将保留它们。 Between the host and the container, they share the linux ACL, so they are just observing the same properties of the files. 它们在主机和容器之间共享linux ACL,因此它们只是观察文件的相同属性。 (Owner, group owner, permissions).
(所有者,组所有者,权限)。 So if your local linux user on the host machine has
UID:GID
1000:1000
, and you create the server.key
file, then the UID:GID
of the file will also be set to 1000:1000
. 因此,如果主机上的本地linux用户具有
UID:GID
1000:1000
,并且创建了server.key
文件,则该文件的UID:GID
也将设置为1000:1000
。 If you then map the file into the container, and observe it from inside - it will also just see 1000:1000
. 如果然后将文件映射到容器中,并从内部进行观察-它也只会看到
1000:1000
。 This means, that we can control the UID:GID
from both inside and outside the container, when mapped from a linux host. 这意味着,当从linux主机映射时,我们可以从容器内部和外部控制
UID:GID
。
Note. 注意。 There does not have to be a user with the
UID
that you assign as owner on a file, it is allowed to set non existent UID:GID
owners of files. 不必具有您分配为文件所有者的
UID
的用户,而是可以设置不存在的文件UID:GID
所有者。
In the postgres alpine
derivative image, the postgres
user/group has UID:GID
70:70
. 在postgres
alpine
派生图像中, postgres
用户/组具有UID:GID
70:70
。 On the debian
derivative the postgres UID:GID
is 999:999
. 在
debian
衍生产品上,postgres的UID:GID
为999:999
。 And not supprising, root has 0:0
on both of them. 并不奇怪,root都在
0:0
上具有0:0
。
This means either have to: 这意味着必须:
UID:GID
of the file server.key
after we start the container, when the volume is already mounted. UID:GID
文件server.key
后 ,我们启动容器,当卷已安装。 UID:GID
of the file server.key
before we start the container server.key
的UID:GID
Since setting this after the container starts, would imply tampering with the startup scripting of the postgres image - let's opt to set them before we start the container. 由于在容器启动后设置此设置,将暗示篡改postgres图像的启动脚本-让我们选择在启动容器之前进行设置。 In the local filesystem where you are mounting them from.
在要从中挂载它们的本地文件系统中。
600
permissions and postgres
as owner of the server.key
600
权限和postgres
作为server.key
所有者 In case you are going with the alpine
derivative, you need to change the owner/group to 70:70
. 如果您要使用
alpine
派生类,则需要将所有者/组更改为70:70
。 If you are using the debian
derivative, then 999:999
. 如果您使用的是
debian
衍生工具,请使用999:999
。
There may not be a user on your host with for example UID
: 70
, but that is not a problem. 您的主机上可能没有用户,例如
UID
: 70
,但这不是问题。
Example: 例:
chown 70:70 server.key # 70:70 for alpine, 999:999 for debian
chmod 600 server.key
640
permissions and root
as owner of the server.key
640
权限和root
作为所有者server.key
This example is also for the alpine image 这个例子也适用于高山图像
Example: 例:
chown 0:70 server.key
chmod 640 server.key
At this point you are good to go. 此时,您可以开始了。 You just need to map the key and certificate into the container, and start postgres like always.
您只需要将密钥和证书映射到容器中,然后像往常一样启动postgres。
I will include a script snippet here, that will do all of this for you for the alpine derivative. 我将在此处包括一个脚本片段,该片段将为您完成所有高山衍生产品。 This example will set the root owner of the server.key and the postgres group owner.
本示例将设置server.key的根所有者和postgres组所有者。
# generate the server.key and server.crt
openssl req -new -text -passout pass:abcd -subj /CN=localhost -out server.req
openssl rsa -in privkey.pem -passin pass:abcd -out server.key
openssl req -x509 -in server.req -text -key server.key -out server.crt
# set postgres (alpine) user as owner of the server.key and permissions to 600
chown 0:70 server.key
chmod 640 server.key
# start a postgres docker container, mapping the .key and .crt into the image.
docker run -d --name postgres \
-v "$PWD/server.crt:/var/lib/postgresql/server.crt:ro" \
-v "$PWD/server.key:/var/lib/postgresql/server.key:ro" \
postgres:11-alpine \
-c ssl=on \
-c ssl_cert_file=/var/lib/postgresql/server.crt \
-c ssl_key_file=/var/lib/postgresql/server.key
I hope this clears things up? 我希望这可以清除一切吗?
Source of the key generating key and certificate is this gist . 这个要点是生成密钥和证书的密钥的来源。
I will include a small guide to how you can build an image yourself, so that you can have a postgres database container with ssl. 我将提供有关如何自己构建映像的小型指南,以便您可以使用带有ssl的postgres数据库容器。 This will work on Windows aswell.
这同样适用于Windows。
Here's the Dockerfile that will do it for you: 这是将为您完成的Dockerfile:
Dockerfile
FROM postgres:11-alpine
# On Windows root will own the files, and they will have permissions 755
COPY server.key /var/lib/postgresql/server.key
COPY server.crt /var/lib/postgresql/server.crt
# update the privileges on the .key, no need to touch the .crt
RUN chmod 600 /var/lib/postgresql/server.key
RUN chown postgres:postgres /var/lib/postgresql/server.key
Build the image with: 使用以下方法生成图像:
docker build -t mypg:01 .
And run with: 并运行:
docker run -d --name postgres mypg:01 \
-c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt \
-c ssl_key_file=/var/lib/postgresql/server.key
In my particular case I was interested in enabling SSL while using the standard postgres image via docker-compose.在我的特殊情况下,我对通过 docker-compose 使用标准 postgres 图像时启用 SSL 感兴趣。 This solution allows
initdb
to run as usual which is useful for setting up the DB and users.此解决方案允许
initdb
照常运行,这对于设置数据库和用户很有用。
docker-compose.yaml
version: '3'
services:
postgres:
image: postgres:12.2
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_USER=myuser
- POSTGRES_HOST_AUTH_MTHOD=trust
volumes:
- ./postgres-initdb:/docker-entrypoint-initdb.d/
- ./postgres-certs/:/var/lib/postgresql/certs/
postgres-initdb/config.sql
ALTER SYSTEM SET ssl_cert_file TO '/var/lib/postgresql/certs/server.crt';
ALTER SYSTEM SET ssl_key_file TO '/var/lib/postgresql/certs/server.key';
ALTER SYSTEM SET ssl TO 'ON';
This will work for any configuration.这适用于任何配置。 For SSL you will also want to generate the certs (taken from a Gist ):
对于 SSL,您还需要生成证书(取自Gist ):
set -euo pipefail
mkdir postgres-certs
cd postgres-certs
openssl req -new -text -passout pass:abcd -subj /CN=localhost -out server.req -keyout privkey.pem
openssl rsa -in privkey.pem -passin pass:abcd -out server.key
openssl req -x509 -in server.req -text -key server.key -out server.crt
chmod 600 server.key
test $(uname -s) == Linux && chown 999 server.key
On macOS because of osxfs driver's behaviour, whatever uid/gid is running in the container is also the uid/gid that owns the mounted files (so files owner on the container will not be the same as the host file's owner).在 macOS 上,由于 osxfs 驱动程序的行为,容器中运行的任何 uid/gid 也是拥有已挂载文件的 uid/gid(因此容器上的文件所有者将与主机文件的所有者不同)。
In MacOS when when we change the file's owner in the container, it writes the owner data at com.docker.owner
extended file attribute(instead of updating the real file's owner).在 MacOS 中,当我们更改容器中文件的所有者时,它会将所有者数据写入
com.docker.owner
扩展文件属性(而不是更新真实文件的所有者)。
so we have to set com.docker.owner
attribute to set the file's owner for containers in docker (just on MacOS).所以我们必须设置
com.docker.owner
属性来设置 docker 中容器的文件所有者(仅在 MacOS 上)。
Note : If your Postgres DB's Image is based on alpine, change 0:999:999
to 0:70:70
注意:如果您的 Postgres DB 的图像基于 alpine,请将
0:999:999
更改为0:70:70
chmod 600 server.key
xattr -w com.docker.owner 0:999:999 server.key # 0:70:70 for alpine-based image```
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.