docker 的 Jenkins 管道:运行 docker 作为特定用户(嵌入式 postgresql
Jenkins pipeline with docker: run docker as specific user (embedded postgresql
嗨 Stack Overflow 社区!
我有一个 Maven - java 项目需要使用 jenkins 管道构建。
为此,我使用 docker 图像 maven:3.3.3
配置了作业。一切正常,除了我使用 ru.yandex.qatools.embed:postgresql-embedded
。这在本地有效,但在詹金斯上它抱怨启动 Postgres:
2019-02-08 09:31:20.366 WARN 140 --- [ost-startStop-1] r.y.q.embed.postgresql.PostgresProcess: Possibly failed to run initdb:
initdb: cannot be run as root
Please log in (using, e.g., "su") as the (unprivileged) user that will own the server process.
2019-02-08 09:31:40.999 ERROR 140 --- [ost-startStop-1] r.y.q.embed.postgresql.PostgresProcess: Failed to read PID file (File '/var/.../target/database/postmaster.pid' does not exist)
java.io.FileNotFoundException: File '/var/.../target/database/postmaster.pid' does not exist
显然,出于安全原因,Postgres 不允许 运行 具有超级用户权限。
我尝试通过创建我自己的 docker-image 版本并将以下内容添加到 DockerFile 来 运行 作为用户:
RUN useradd myuser
USER myuser
这在我从服务器终端启动 docker 图像时有效。但是通过使用 jenkins 管道,whoami 仍然打印 'root',这表明 Jenkins 管道在方案后面使用 run -u
,这将否决 DockerFile?
我的流水线作业目前就这么简单:
pipeline {
agent {
docker {
image 'custom-maven:1'
}
}
stages {
stage('Checkout') {
...
}
stage('Build') {
steps {
sh 'whoami'
sh 'mvn clean install'
}
}
}
}
那么,我的问题是:如何以不同的用户身份启动此 docker 图像?或者在 运行ning mvn clean install
?
之前切换用户
更新:
通过在 jenkins 管道中添加 -u myuser 作为参数,我确实以正确的用户身份登录,但是作业无法访问 jenkins-log 文件(希望这是唯一的问题)。用户 myuser 被添加到组 root,但这没有区别:
agent {
docker {
image 'custom-maven:1'
args '-u myuser'
}
}
错误:
sh: 1: cannot create /var/.../jenkins-log.txt: Permission denied
sh: 1: cannot create /var/.../jenkins-result.txt.tmp: Permission denied
mv: cannot stat ‘/var/.../jenkins-result.txt.tmp’: No such file or directory
touch: cannot touch ‘/var/.../jenkins-log.txt’: Permission denied
我已经解决了我们案例中的问题。我所做的是 sudo
在 mvn
命令之前。请记住,每个 sh
步骤都有自己的 shell,因此您需要在每个 sh
步骤中执行 sudo
:
sh 'sudo -u <youruser> mvn <clean or whatever> -f <path/to/pomfile.xml>'
必须在 Dockerfile 中创建用户。我在没有密码的情况下创建了它,但我认为这不重要,因为你是 root...
您必须使用 sudo
而不是切换用户或其他方式,否则您需要提供密码。
这远不是一个干净的方法...我建议除非你真的需要(比如 运行 一个嵌入式 postgres),否则不要乱用用户切换
@Thomas Stubbe
我遇到了与您上面提到的几乎相同的错误。我还有一张图片,上面有 postgresql。在 Dockerfile 上,我创建了一个名为 tdv 的用户,并在 Container 上使用 id 命令检查 tdv 权限为 1000:1000。我可以通过 Jenkins 管道启动容器,但它无法执行 sh 命令,即使我为每个命令添加 sudo -u tdv 也是如此。有没有做其他配置?
我的 Jenkins Pileline 脚本如下:
pipeline{
agent none
stages{
stage('did operation inside container'){
agent {
docker{
image 'tdv/tdv-test:8.2'
label 'docker_machine'
customWorkspace "/opt/test"
registryUrl 'https://xxxx.xxxx.com'
registryCredentialsId '8269c5cd-321e-4fab-919e-9ddc12b557f3'
args '-u tdv --name tdv-test -w /opt/test -v /opt/test:/opt/test:rw,z -v /opt/test@tmp:/opt/test@tmp:rw,z -p 9400:9400 -p 9401:9401 -p 9402:9402 -p 9403:9403 -p 9407:9407 -p 9303:9303 --cpus=2.000 -m=4g xxx.xxx.com/tdv/tdv-test:8.2 tdv.server'
}
}
steps{
sh 'sudo tdv whoami'
sh 'sudo tdv pwd'
sh 'sudo tdv echo aaa'
}
}
}
}
Job 运行 之后,我可以检查 Container 是否真的启动了。但它仍然会出现如下错误
$ docker top f1140072d77c5bed3ce43a5ad2ab3c4be24e8c32cf095e83c3fd01a883e67c4e -eo pid,comm
ERROR: The container started but didn't run the expected command. Please double check your ENTRYPOINT does execute the command passed as docker run argument, as required by official docker images (see https://github.com/docker-library/official-images#consistency for entrypoint consistency requirements).
Alternatively you can force image entrypoint to be disabled by adding option `--entrypoint=''`.
[Pipeline] {
[Pipeline] sh
sh: /opt/test@tmp/durable-081990da/jenkins-log.txt: Permission denied
sh: /opt/test@tmp/durable-081990da/jenkins-result.txt.tmp: Permission denied
touch: cannot touch ‘/opt/test@tmp/durable-081990da/jenkins-log.txt’: Permission denied
mv: cannot stat ‘/opt/test@tmp/durable-081990da/jenkins-result.txt.tmp’: No such file or directory
touch: cannot touch ‘/opt/test@tmp/durable-081990da/jenkins-log.txt’: Permission denied
touch: cannot touch ‘/opt/test@tmp/durable-081990da/jenkins-log.txt’: Permission denied
解决方案
您目前有 sh 'sudo tdv whoami'
我认为你应该像这样在 sudo 之后添加 -u
标志:
sh 'sudo -u tdv whoami'
嗨 Stack Overflow 社区!
我有一个 Maven - java 项目需要使用 jenkins 管道构建。
为此,我使用 docker 图像 maven:3.3.3
配置了作业。一切正常,除了我使用 ru.yandex.qatools.embed:postgresql-embedded
。这在本地有效,但在詹金斯上它抱怨启动 Postgres:
2019-02-08 09:31:20.366 WARN 140 --- [ost-startStop-1] r.y.q.embed.postgresql.PostgresProcess: Possibly failed to run initdb:
initdb: cannot be run as root
Please log in (using, e.g., "su") as the (unprivileged) user that will own the server process.
2019-02-08 09:31:40.999 ERROR 140 --- [ost-startStop-1] r.y.q.embed.postgresql.PostgresProcess: Failed to read PID file (File '/var/.../target/database/postmaster.pid' does not exist)
java.io.FileNotFoundException: File '/var/.../target/database/postmaster.pid' does not exist
显然,出于安全原因,Postgres 不允许 运行 具有超级用户权限。
我尝试通过创建我自己的 docker-image 版本并将以下内容添加到 DockerFile 来 运行 作为用户:
RUN useradd myuser
USER myuser
这在我从服务器终端启动 docker 图像时有效。但是通过使用 jenkins 管道,whoami 仍然打印 'root',这表明 Jenkins 管道在方案后面使用 run -u
,这将否决 DockerFile?
我的流水线作业目前就这么简单:
pipeline {
agent {
docker {
image 'custom-maven:1'
}
}
stages {
stage('Checkout') {
...
}
stage('Build') {
steps {
sh 'whoami'
sh 'mvn clean install'
}
}
}
}
那么,我的问题是:如何以不同的用户身份启动此 docker 图像?或者在 运行ning mvn clean install
?
更新:
通过在 jenkins 管道中添加 -u myuser 作为参数,我确实以正确的用户身份登录,但是作业无法访问 jenkins-log 文件(希望这是唯一的问题)。用户 myuser 被添加到组 root,但这没有区别:
agent {
docker {
image 'custom-maven:1'
args '-u myuser'
}
}
错误:
sh: 1: cannot create /var/.../jenkins-log.txt: Permission denied
sh: 1: cannot create /var/.../jenkins-result.txt.tmp: Permission denied
mv: cannot stat ‘/var/.../jenkins-result.txt.tmp’: No such file or directory
touch: cannot touch ‘/var/.../jenkins-log.txt’: Permission denied
我已经解决了我们案例中的问题。我所做的是 sudo
在 mvn
命令之前。请记住,每个 sh
步骤都有自己的 shell,因此您需要在每个 sh
步骤中执行 sudo
:
sh 'sudo -u <youruser> mvn <clean or whatever> -f <path/to/pomfile.xml>'
必须在 Dockerfile 中创建用户。我在没有密码的情况下创建了它,但我认为这不重要,因为你是 root...
您必须使用 sudo
而不是切换用户或其他方式,否则您需要提供密码。
这远不是一个干净的方法...我建议除非你真的需要(比如 运行 一个嵌入式 postgres),否则不要乱用用户切换
@Thomas Stubbe
我遇到了与您上面提到的几乎相同的错误。我还有一张图片,上面有 postgresql。在 Dockerfile 上,我创建了一个名为 tdv 的用户,并在 Container 上使用 id 命令检查 tdv 权限为 1000:1000。我可以通过 Jenkins 管道启动容器,但它无法执行 sh 命令,即使我为每个命令添加 sudo -u tdv 也是如此。有没有做其他配置?
我的 Jenkins Pileline 脚本如下:
pipeline{
agent none
stages{
stage('did operation inside container'){
agent {
docker{
image 'tdv/tdv-test:8.2'
label 'docker_machine'
customWorkspace "/opt/test"
registryUrl 'https://xxxx.xxxx.com'
registryCredentialsId '8269c5cd-321e-4fab-919e-9ddc12b557f3'
args '-u tdv --name tdv-test -w /opt/test -v /opt/test:/opt/test:rw,z -v /opt/test@tmp:/opt/test@tmp:rw,z -p 9400:9400 -p 9401:9401 -p 9402:9402 -p 9403:9403 -p 9407:9407 -p 9303:9303 --cpus=2.000 -m=4g xxx.xxx.com/tdv/tdv-test:8.2 tdv.server'
}
}
steps{
sh 'sudo tdv whoami'
sh 'sudo tdv pwd'
sh 'sudo tdv echo aaa'
}
}
}
}
Job 运行 之后,我可以检查 Container 是否真的启动了。但它仍然会出现如下错误
$ docker top f1140072d77c5bed3ce43a5ad2ab3c4be24e8c32cf095e83c3fd01a883e67c4e -eo pid,comm
ERROR: The container started but didn't run the expected command. Please double check your ENTRYPOINT does execute the command passed as docker run argument, as required by official docker images (see https://github.com/docker-library/official-images#consistency for entrypoint consistency requirements).
Alternatively you can force image entrypoint to be disabled by adding option `--entrypoint=''`.
[Pipeline] {
[Pipeline] sh
sh: /opt/test@tmp/durable-081990da/jenkins-log.txt: Permission denied
sh: /opt/test@tmp/durable-081990da/jenkins-result.txt.tmp: Permission denied
touch: cannot touch ‘/opt/test@tmp/durable-081990da/jenkins-log.txt’: Permission denied
mv: cannot stat ‘/opt/test@tmp/durable-081990da/jenkins-result.txt.tmp’: No such file or directory
touch: cannot touch ‘/opt/test@tmp/durable-081990da/jenkins-log.txt’: Permission denied
touch: cannot touch ‘/opt/test@tmp/durable-081990da/jenkins-log.txt’: Permission denied
解决方案
您目前有 sh 'sudo tdv whoami'
我认为你应该像这样在 sudo 之后添加 -u
标志:
sh 'sudo -u tdv whoami'