Dockerコンテナで実行しているJenkins Serverがあり、ホストシステムのdockerにアクセスできますが、これまでのところうまく機能しています。ここで、Dockerコンテナ内のスクリプトをテストするパイプラインをセットアップします。
Jenkinsfile:
pipeline {
agent { docker 'nginx:1.11' }
stages {
stage('build') {
steps {
sh 'nginx -t'
}
}
}
}
エラーメッセージ:
> + docker pull nginx:1.11
>
> Warning: failed to get default registry endpoint from daemon (Got
> permission denied while trying to connect to the Docker daemon socket
> at unix:///var/run/docker.sock: Get
> http://%2Fvar%2Frun%2Fdocker.sock/v1.29/info: dial unix
> /var/run/docker.sock: connect: permission denied). Using system
> default: https://index.docker.io/v1/
>
> Got permission denied while trying to connect to the Docker daemon
> socket at unix:///var/run/docker.sock: Post
> http://%2Fvar%2Frun%2Fdocker.sock/v1.29/images/create?fromImage=nginx&tag=1.11:
> dial unix /var/run/docker.sock: connect: permission denied
>
> script returned exit code 1
私の問題は、jenkinsがsudoでdockerコマンドを実行する必要があることですが、sudoでコマンドを実行しているエージェントを言う方法は?
同じ問題に直面しました。コンソールログを分析した結果、Docker Jenkinsプラグインが特定のオプション-u 107:112で新しいコンテナーを開始することが理由であることがわかりました。
...
docker run -t -d -u 107:112 ...
...
次のような多くのオプションを試した後、jenkins
をSudoグループに追加します(jenkins
ユーザーがコンテナに存在しないため機能しませんでした)、USER root
into Dockerfile
、...しかし、それらのどれもトリックを行いません。
最後に、docker agentでargsを使用して-オプションを上書きするソリューションを見つけました。これは私のJenkinsfile:
pipeline {
agent {
docker {
image 'ubuntu'
args '-u root:Sudo -v $HOME/workspace/myproject:/myproject'
}
}
stages {
stage("setup_env") {
steps {
sh 'apt-get update -y'
sh 'apt-get install -y git build-essential gcc cmake make'
}
}
stage("install_dependencies") {
steps {
sh 'apt-get install -y libxml2-dev'
}
}
stage("compile_dpi") {
steps {
sh 'cd /myproject && make clean && make -j4'
}
}
stage("install_dpi") {
steps {
sh 'cd /myproject && make install'
}
}
stage("test") {
steps {
sh 'do some test here'
}
}
}
post {
success {
echo 'Do something when it is successful'
bitbucketStatusNotify(buildState: 'SUCCESSFUL')
}
failure {
echo 'Do something when it is failed'
bitbucketStatusNotify(buildState: 'FAILED')
}
}
}
ここにはセキュリティの問題があるかもしれませんが、私の場合は問題ではありません。
コンテナ内のjenkinsグループIDを、ボリュームをマウントしたdockerソケットのグループIDと一致させて、問題を別の方法で解決します。ルートとして実行し、ソケットのgidを検索し、現在のコンテナー内のgidのそれと一致しない場合、コンテナー内でそれを修正するgroupmod
を実行するエントリポイントを使用してこれを行います。次に、jenkins
ユーザーに権限をドロップして、Jenkinsを起動します。このエントリポイントはすべてのスタートアップで実行されますが、起動されるJenkinsアプリに対してはかなり透過的に実行されます。
これを実行するすべての手順は、このgithubリポジトリに含まれています。 https://github.com/Sudo-bmitch/jenkins-docker/
次の方法で回避できます。
1- Dockerfile
でsudoersファイルにジェンキンを追加します。
RUN echo "jenkins ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
2- Jenkinsfile
に追加のステップを追加して、ジェンキンにdockerを使用する適切な権限を付与します。
pipeline {
agent none
stages {
stage("Fix the permission issue") {
agent any
steps {
sh "Sudo chown root:jenkins /run/docker.sock"
}
}
stage('Step 1') {
agent {
docker {
image 'nezarfadle/tools'
reuseNode true
}
}
steps {
sh "ls /"
}
}
}
}
私のために働いたのは
node() {
String jenkinsUserId = sh(returnStdout: true, script: 'id -u jenkins').trim()
String dockerGroupId = sh(returnStdout: true, script: 'getent group docker | cut -d: -f3').trim()
String containerUserMapping = "-u $jenkinsUserId:$dockerGroupId "
docker.image('image')
.inside(containerUserMapping + ' -v /var/run/docker.sock:/var/run/docker.sock:ro') {
sh "..."
}
}
この方法では、コンテナ内のユーザーは引き続きjenkinsユーザーID +グループIDを使用して、共有データとの権限の競合を回避しますが、Dockerソケット(/var/run/docker.sockへのアクセスに必要なコンテナー内のdockerグループのメンバーでもあります)
追加のスクリプトやdockerfilesを必要としないため、このソリューションを好む
私はちょうど同じ問題を抱えていました。 jenkinsユーザーをdockerグループに追加する必要があります。
DOCKER_SOCKET=/var/run/docker.sock
DOCKER_GROUP=docker
JENKINS_USER=jenkins
if [ -S ${DOCKER_SOCKET} ]; then
DOCKER_GID=$(stat -c '%g' ${DOCKER_SOCKET})
Sudo groupadd -for -g ${DOCKER_GID} ${DOCKER_GROUP}
Sudo usermod -aG ${DOCKER_GROUP} ${JENKINS_USER}
fi
# Start Jenkins service
Sudo service jenkins restart
上記を実行すると、パイプラインが正常にドッカーを開始します
私はこれに対してかなり良い解決策を見つけたかもしれません。
Jenkinsをコンテナーとして実行し、それを使用して、実行中のdockerhostでコンテナーを構築します。これを行うには、/var/run/docker.sock
をボリュームとしてコンテナーに渡します。
免責事項を繰り返しますが、他の人々はすでに述べています:Dockerソケットへのアクセスを許可することは、基本的にマシンへのルートアクセスを許可することに似ています-注意してください!
Jenkins Imageには既にdockerがインストールされていると思います。
これは、Dockerバイナリが$PATH
の最初のディレクトリにないという事実に基づいています。基本的に、単純なdocker
コマンドの代わりにSudo docker
を実行する(およびパラメーターを渡す)シェルスクリプトを配置します。
このようなファイルをjenkinsリポジトリに追加し、docker_Sudo_overwrite.sh
という名前を付けます。
#! /bin/sh
# This basically is a workaround to add Sudo to the docker command, because aliases don't seem to work
# To be honest, this is a horrible workaround that depends on the order in $PATH
# This file needs to be place in /usr/local/bin with execute permissions
Sudo /usr/bin/docker $@
次に、Jenkins Dockerfile
を次のように拡張します。
# Now we need to allow jenkins to run docker commands! (This is not elegant, but at least it's semi-portable...)
USER root
## allowing jenkins user to run docker without specifying a password
RUN echo "jenkins ALL=(ALL) NOPASSWD: /usr/bin/docker" >> /etc/sudoers
# Create our alias file that allows us to use docker as Sudo without writing Sudo
COPY docker_Sudo_overwrite.sh /usr/local/bin/docker
RUN chmod +x /usr/local/bin/docker
# switch back to the jenkins-user
USER jenkins
これにより、jenkinsサービスユーザーは、sudoを使用してrootとしてdockerバイナリを実行できます(パスワードを入力しなくても)。次に、スクリプトを/usr/local/bin/docker
にコピーします。これは、実際のバイナリを「オーバーレイ」し、Sudo
で実行します。役立つ場合は、 Github の私の例をご覧ください。
ここで同じ問題。
[...]
agent { docker 'whatever_I_try_doesnt_work'} # Sudo, jenkins user in dockerroot group etc
[...]
したがって、次善策として、パイプラインのビルドステージのステップの1つとして追加します。
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'Sudo docker pull python:3.5.1'
}
}
}
}