大蛇丸が料理をしたら、っていう発想ができるような人間になっていきたい今日この頃です。
#目的
- 仮想化の新潮流であるコンテナ技術をDockerを用いて理解したい
- CI/CDツールの環境構築にも使用されているコンテナ技術でJenkinsを構築したい
- できたらPCのローカル環境は綺麗なままにしたい
#ターゲット
- コンテナ技術を用いてCI/CDツールの導入を考えている方
- これからDockerを触ってみたい方 ※Dockerの説明は行いません。本記事は環境構築のみです。
#参考書籍
Docker/Kubernetes 実践コンテナ開発入門(著者:山田明憲)
#設計
当初は参考書籍に記述されているように、Macに直接Dockerをインストールしようとしました。
しかし、Macに直接Dockerを入れてしまうとDockerの複数バージョンを管理するのが難しいです。
また、ローカル環境にDocker資材などが混じり汚れてしまいます。
そこで仮想マシンを用意し、その中にDockerをインストールするようにしました。
これにより仮想マシン単位でDockerのバージョン管理ができます。
また、環境構築をソースコード(Vagrantfile)で管理できるため、2回目以降の構築時間短縮にも繋がります。
#構築
##仮想マシンの準備
###VirtualBoxをインストール
作業環境:ホストOS
仮想化ソフトウェアのVirtualBoxをインストールします。(ホストOSに合わせてpkgをダウンロードしてください。)
※VagrantにはVirtualBoxは含まれていないので別途インストールする必要があります。
###Vagrantをインストール
作業環境:ホストOS
仮想化ソフトウェアのラッパーツールであるVagrantをインストールします。(ホストOSに合わせてdmgをダウンロードしてください。)
###仮想マシンを作成
####CentOS7のBoxを追加
作業環境:ホストOS
仮想マシンのBox(イメージファイル)を追加します。
今回は公式から提供されているCentOS7のBoxを追加します。
# Vagrantインストール直後
$ vagrant box list
There are no installed boxes! Use `vagrant box add` to add some.
# CentOS7のBoxを追加
$ vagrant box add centos/7
==> box: Loading metadata for box 'centos/7'
box: URL: https://atlas.hashicorp.com/centos/7
This box can work with multiple providers! The providers that it
can work with are listed below. Please review the list and choose
the provider you will be working with.
1) hyperv
2) libvirt
3) virtualbox
4) vmware_desktop
# 今回はVirtualBoxを使用しているので「3:virtualbox」を選択
Enter your choice: 3
==> box: Adding box 'centos/7' (v1708.01) for provider: virtualbox
box: Downloading: https://vagrantcloud.com/centos/boxes/7/versions/1708.01/providers/virtualbox.box
==> box: Successfully added box 'centos/7' (v1708.01) for 'virtualbox'!
# Box追加後
$ vagrant box list
centos/7 (virtualbox, 1708.01)
####初期設定
作業環境:ホストOS
仮想マシン構築に使用するVagrantfileを作成します。
# 今回はカレントディレクトリ直下に「centos7」というVagrantfileを格納するディレクトリを作成
$ mkdir centos7
# 作成したディレクトリの確認
$ ls -latr | grep centos7
drwxr-xr-x 5 ogino staff 160 5 19 16:21 centos7
# 作成したディレクトリに移動
$ cd centos7/
# 初期設定を実行
$ vagrant init centos/7
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
# 初期設定によりVagrantfileが作成されたことを確認 ※他のファイルやディレクトリは後ほど説明します
$ ls -latr
total 8
drwxr-xr-x 4 ogino staff 128 5 10 15:28 .vagrant
drwxr-xr-x 4 ogino staff 128 5 19 15:56 key
-rw-r--r-- 1 ogino staff 3010 5 19 16:21 Vagrantfile ←VagrantfileができていればOK
drwxr-xr-x 5 ogino staff 160 5 19 16:21 .
drwxr-xr-x+ 47 ogino staff 1504 5 20 14:26 ..
# 作成したVagrantfileを元に仮想マシンの状態を確認
$ vagrant status
Current machine states:
default not created (virtualbox) ←まだ仮想マシンは作成されていないのでOK
The environment has not yet been created. Run `vagrant up` to
create the environment. If a machine is not created, only the
default provider will be shown. So if a provider is not listed,
then the machine is not created for that environment.
####仮想マシンの操作
作業環境:ホストOS
Vagrantfileがあるディレクトリ上から仮想マシンを起動させます。
# Vagrantfileがあるディレクトリにいることを確認
$ pwd
/Users/ogino/centos7
# Vagrantfileがあることを確認
$ ls -latr Vagrantfile
-rw-r--r-- 1 ogino staff 3010 5 19 16:21 Vagrantfile
# 仮想マシンを起動
$ vagrant up
<中略>
==> default: Machine booted and ready! ←仮想マシンが起動したようなのでOK
==> default: Checking for guest additions in VM...
default: No guest additions were detected on the base box for this VM! Guest
default: additions are required for forwarded ports, shared folders, host only
default: networking, and more. If SSH fails on this machine, please install
default: the guest additions and repackage the box to continue.
default:
default: This is not an error message; everything may continue to work properly,
default: in which case you may ignore this message.
==> default: Configuring and enabling network interfaces...
==> default: Rsyncing folder: /Users/ogino/centos7/ => /vagrant
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.
# 仮想マシンの状態確認
vagrant status
Current machine states:
default running (virtualbox) ←起動中になっているのでOK
The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
次は仮想マシンにSSH接続でログインしてみます。
# 仮想マシンにSSH接続でログイン
$ vagrant ssh
Last login: Tue May 19 06:04:50 2020 from 10.0.2.2
# 仮想マシンのホスト名
$hostname
localhost.localdomain
# ログインユーザは「vagrant」
$ who
vagrant pts/0 2020-05-20 05:48 (10.0.2.2)
# sudoコマンドも使用可能
$ sudo hostname
localhost.localdomain
# 仮想マシンからログアウト
# exit ←Macなら「control + d」でもログアウトできます
ログアウト
Connection to 127.0.0.1 closed.
最後に仮想マシンを停止させます。
# 仮想マシンを停止
vagrant halt
==> default: Attempting graceful shutdown of VM...
# 仮想マシンが停止していることを確認
vagrant status
Current machine states:
default poweroff (virtualbox) ←電源が落ちているのでOK
The VM is powered off. To restart the VM, simply run `vagrant up`
VirtualBoxのアプリケーションからも作成した仮想マシンを確認することができます。
(今回はVagrantを使用するので、GUIではなくCUIベースで環境構築を進めていきます。)
####仮想マシンのネットワーク設定
作業環境:ホストOS
Vagrantで作成した仮想マシンのネットワークは、
デフォルトだとホストオンリーアダプタといってホストとゲストの間でしか通信ができません。
それだと何かと不便なので、内部ネットワークを利用してホストとゲスト、ゲスト間同士の通信ができる
プライベートネットワークを設定しておきます。
# 仮想マシンにログイン
$ vagrant ssh
Last login: Tue May 19 06:04:50 2020 from 10.0.2.2
# net-tools系のコマンドは標準でインストールされないためyumを使ってインストール
# 全て「y:Yes」で回答してOK
$ sudo yum install net-tools
# ホストオンリーアダプタ時のipアドレス(et0)を確認
$ ifconfig
# 仮想マシンからログアウト
$ exit
logout
Connection to 127.0.0.1 closed.
# 仮想マシンを停止させる(Vagrantfileの修正内容を反映させるには再起動が必要なため)
$ vagrant halt
==> default: Attempting graceful shutdown of VM...
# Vagrantfileを修正
$ vi Vagrantfile
※修正内容は、以下の行のコメントマーク(#)を外します
# config.vm.network "forwarded_port", guest: 80, host: 8080
# config.vm.network "private_network", ip: "192.168.33.10"
# 仮想マシンを起動
$ vagrant up
# 仮想マシンにSSH接続
$ vagrant ssh
Last login: Wed May 20 06:27:38 2020 from 10.0.2.2
# プライベートネットワーク時のipアドレス(et1)を確認
$ ifconfig
####仮想マシンのユーザ設定
今回の環境構成だと、VagrantユーザのUID(1000)とJenkinsユーザのUID(1000)が衝突してしまう問題があります。
それを回避するためにVagrantユーザのUIDを別の値に変更します。
出典:公式 jenkins 配布コンテナは UID 1000 の jenkins ユーザーで動作する
参考:出来るだけ最短で Jenkins 環境を試したい(jenkins container + docker CE + CentOS7 + vagrant)
#####新規ユーザの作成
作業環境:仮想マシン
# 仮想マシンのPrivate IPアドレスをメモする
# ※新規ユーザで仮想マシンにアクセスする際はVagrantを経由しないためIPアドレスを指定する必要があります
$ ip addr show eth1
# 「USERNAME1」変数に追加するユーザ名を設定
$ USERNAME1=ok2
# ユーザを追加
$ sudo useradd -m -u 1001 -g vagrant $USERNAME1
# 追加したユーザに切り替える
$ sudo su - $USERNAME1
# カレントディレクトリが新規ユーザのホームディレクトリに切り替わっていることを確認
$ pwd
/home/ok2
# 「.ssh」ディレクトリを作成
$ mkdir .ssh
# 「.ssh」ディレクトリのアクセス権限を変更
$ chmod 700 .ssh/
# 新規ユーザからログアウト
$ exit
logout
# 新規ユーザのパスワードを設定
$ sudo passwd $USERNAME1
Changing password for user ok2.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
# Vagrantユーザからログアウト
$ exit
logout
Connection to 127.0.0.1 closed.
#####鍵の作成
作業環境:ホストOS
# 公開鍵/秘密鍵を作成
$ ssh-keygen -t rsa -f ./id_rsa
# 公開鍵の中身をメモする ※仮想マシン側にも鍵追加を行うため
$ cat id_rsa.pub
#####鍵の追加
作業環境:仮想マシン
# Vagrantユーザで仮想マシンにログイン
vagrant ssh
Last login: Wed May 20 09:03:38 2020 from 10.0.2.2
# 「USERNAME1」に追加ユーザ名を設定
$ USERNAME1=ok2
# 追加ユーザに切り替え
$ sudo su - $USERNAME1
Last login: Wed May 20 09:05:30 UTC 2020 on pts/0
# 「.ssh」ディレクトリに移動
$ cd .ssh
# 認証鍵リストにホストOSで作成した公開鍵を追加
$ vi authorized_keys
# 認証鍵リストを確認
$ ls -latr
total 4
drwx------. 3 ok2 vagrant 95 May 20 09:06 ..
-rw-r--r--. 1 ok2 vagrant 403 May 20 09:13 authorized_keys
drwx------. 2 ok2 vagrant 29 May 20 09:13 .
# 認証鍵リストのアクセス権限を変更
$ chmod 600 authorized_keys
# 認証鍵リストのアクセス権限が変更されていることを確認
$ ls -latr
total 4
drwx------. 3 ok2 vagrant 95 May 20 09:06 ..
-rw-------. 1 ok2 vagrant 403 May 20 09:13 authorized_keys
drwx------. 2 ok2 vagrant 29 May 20 09:13 .
# 追加ユーザからログアウト
$ exit
logout
# Vagrantユーザからログアウト
$ exit
logout
Connection to 127.0.0.1 closed.
#####新規ユーザでのログイン
作業環境:ホストOS
# 「USERNAME1」変数に追加ユーザを設定
$ USERNAME1=ok2
# SSH接続で仮想マシン(Private IPアドレス)に接続
# ※以下は、known_hostsに過去のアクセスログが残っていたためエラー
$ssh -i ./id_rsa $USERNAME1@192.168.33.10
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
<中略>
Host key verification failed.
# known_hosts内の情報を全て削除
$ vi /Users/ogino/.ssh/known_hosts
# 再度SSH接続
$ ssh -i ./id_rsa $USERNAME1@192.168.33.10
#####ユーザUIDの変更
作業環境:仮想マシン
# Vagrantが使用しているIDを確認(1000が指定されていること)
$ sudo id vagrant
uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant)
# VagrantのUIDを1002に変更
$ sudo usermod -u 1002 vagrant
# Vagrantが使用しているIDを確認(1002が指定されていること)
$ sudo id vagrant
uid=1002(vagrant) gid=1000(vagrant) groups=1000(vagrant)
# ユーザ情報からも1000が使用されていないことを確認
$ grep 1000 /etc/passwd
vagrant:x:1002:1000:vagrant:/home/vagrant:/bin/bash
ok2:x:1001:1000::/home/ok2:/bin/bash
# 追加ユーザからログアウト
exit
上記の対応をすることで、Jenkins導入後にUIDの衝突を回避することができます。
##Dockerの準備
###Dockerのインストール
作業環境:仮想マシン
コンテナ仮想化ソフトウェアのDockerを仮想マシンにインストールします。
# yumを最新にアップデート
$ sudo yum update ←全て「y:Yes」で回答
# Dockerのインストール
$ sudo yum -y install docker
# Dockerデーモンの起動
$ sudo systemctl start docker
# Dockerのブート時自動起動を設定
$ sudo systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
# Dockerのバージョンを確認
$ docker --version
Docker version 1.13.1, build 64e9980/1.13.1 ←無事にインストールできていることを確認
Dockerはインストール時点ではroot権限(sudoをつけて実行)がないと権限エラーが発生します。
毎度 sudo
をつけるのは手間なので、実行ユーザをDockerグループに所属させます。
# Vagrantユーザで仮想マシンにログイン
$ vagrant ssh
Last login: Wed May 20 13:18:33 2020 from 10.0.2.2
# インストール時点ではsudoをつけて実行しないと権限エラーが発生
$ docker images
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.26/images/json: dial unix /var/run/docker.sock: connect: permission denied
# Dockerグループを作成
$ sudo groupadd docker
# 現行ユーザをdockerグループに所属
$ sudo gpasswd -a $USER docker
ユーザ vagrant をグループ docker に追加
# dockerデーモンを再起動
$ sudo systemctl restart docker
# ログアウト
$ exit
logout
Connection to 192.168.33.10 closed.
# 再ログイン
$ vagrant ssh
Last login: Wed May 20 13:18:33 2020 from 10.0.2.2
# Dockerコマンドがsudoなしで実行できることを確認
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
###Docker Composeのインストール
作業環境:仮想マシン
複数のコンテナを使う Docker アプリケーションを定義・実行するツールのDocker Composeをインストールします。
インストールするバージョンについては、公式ガイド を確認して、最新バージョン のものを入れるようにしてください。
# 2020/05/20時点の安定版は1.25.5
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 638 100 638 0 0 1641 0 --:--:-- --:--:-- --:--:-- 1640
100 16.7M 100 16.7M 0 0 785k 0 0:00:21 0:00:21 --:--:-- 1201k
# ダウンロードしたバイナリに、実行可能権限を付与
$ sudo chmod +x /usr/local/bin/docker-compose
# Docker Composeのインストールができたことを確認
$ docker-compose --version
docker-compose version 1.25.5, build 8a1c60f6
参考:Install Docker Compose on CentOS 7
##Jenkinsの準備
###Jenkins(マスタ)コンテナの作成
####docker-compose.ymlの作成
作業環境:仮想マシン
docker-compose.ymlは、Dockerイメージをビルドするための情報やコンテナ起動するための情報、
使用するDockerネットワークなどを記載する設定ファイルです。
※書籍にある jenkinsci
イメージを使用するとプラグインのインストールでエラーになるので、今回は jenkins
イメージを使用します。
version: "3"
services:
master:
container_name: master
image: jenkins/jenkins
ports:
- 8080:8080
volumes:
- ./jenkins_home:/var/jenkins_home:z
今回はこれをDocker実行環境(仮想マシン内)に作成していきます。
# 上記のdocker-compose.ymlをコピーして貼り付け
$ vi docker-compose.yml
####Jenkinsの起動
作業環境:仮想マシン
# コンテナ起動
$ docker-compose up
<中略>
master | touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
master | Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
master exited with code 1
# マウントしようとしたディレクトリで権限エラーが発生したため、所有ユーザをJenkins(1000)に変更
$ sudo chown 1000 -R jenkins_home/
# 再度コンテナ起動
$ docker-compose up
Starting master ... done
Attaching to master
<中略>
master |
master | *************************************************************
master | *************************************************************
master | *************************************************************
master |
master | Jenkins initial setup is required. An admin user has been created and a password generated.
master | Please use the following password to proceed to installation:
master |
master | <ここに初回ログイン時に求められるパスワードが表示> ←初期設定時に使用するのでメモに残しておきます
master |
master | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
master |
master | *************************************************************
master | *************************************************************
master | *************************************************************
master |
<中略>
master | 2020-05-20 13:51:53.388+0000 [id=19] INFO hudson.WebAppMain$3#run: Jenkins is fully up and running ←起動完了
####初期設定
作業環境:ホストOS
Jenkins(マスタ)コンテナを起動後に、http://<仮想マシンのPrivate IPアドレス>:8080/ にアクセスします。
コンテナ起動時にコンソールに表示されていたパスワードを入力します。
Install suggested plugins を選択しプラグインをインストールします。
ユーザ情報を登録します。
JenkinsのURLを決められますが、デフォルトのまま次に進みます。
セットアップ内容に不備がなければ Start using Jenkin を選択します。
JenkinsのTop画面が表示されれば成功です。
###Jenkins(スレーブ)コンテナの作成
####Jenkins(マスタ)コンテナのSSH鍵の作成
作業環境:コンテナ
Jenkinsのマスタ(コンテナ)からスレーブ(コンテナ)へ疎通が必要なため、
接続用に先ほど作成したマスタのSSH鍵を作成します。
# マスタコンテナ起動 ※オプションに -d をつけることでバックグラウンドで実行されます
$ docker-compose up -d
Starting master ... done
# コンテナ内でSSH鍵を作成
$ docker container exec -it master ssh-keygen -t rsa -C ""
作業環境:仮想マシン
コンテナのディレクトリを仮想マシン上にマウントしているので、仮想マシンから作成した公開鍵を確認します。
# 公開鍵を確認
$ sudo cat jenkins_home/.ssh/id_rsa.pub
<表示された公開鍵をメモ>
# 秘密鍵を確認
$ sudo cat jenkins_home/.ssh/id_rsa
<表示された秘密鍵をメモ>
####docker-compose.ymlの作成
作業環境:仮想マシン
version: "3"
services:
master:
container_name: master
image: jenkins/jenkins
ports:
- 8080:8080
volumes:
- ./jenkins_home:/var/jenkins_home:z
links:
- slave01
slave01:
container_name: slave01
image: jenkinsci/ssh-slave
environment:
- JENKINS_SLAVE_SSH_PUBKEY=<上記でメモした公開鍵>
Jenkins(マスタ)コンテナ作成時に使用したymlファイルに追記します。
# 上記のdocker-compose.ymlをコピーして貼り付け
$ vi docker-compose.yml
####Jenkinsの起動
作業環境:仮想マシン
# コンテナ起動
$ docker-compose up -d
# 起動中のコンテナを確認
$ docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------
master /sbin/tini -- /usr/local/b ... Up 50000/tcp, 0.0.0.0:8080->8080/tcp
slave01 setup-sshd Up 22/tcp ←今回追加したスレーブコンテナがあればOK
####追加設定
作業環境:ホストOS
JenkinsのTopページから「Jenkinsの管理 - ノードの管理 - 新規ノード作成」を選択します。
ノード名には「Slave01」、Permanet Agentにはチェックをつけて、OKを選択します。
詳細設定の各欄に必要な情報を入力します。
ノード名:slave01
リモートFSルート:/home/jenkins
起動方法:SSH経由〜
ホスト:slave01
認証情報:後ほど作成した認証情報
Host Key Verification Strategy:Non verifying〜
高度な設定 - Javaのパス:/usr/local/openjdk-8/bin/java
認証情報の追加ボタンを押して、認証情報を追加します。
種類:SSH〜
ID:slave01
秘密鍵:Jenkins(マスタ)コンテナのSSH秘密鍵
パスフレーズ:SSH鍵作成時に設定したパスワード
ノード一覧画面にmasterとslave01が表示されていれば環境構築終了です。
#最後に
今回はJenkinsの環境構築のみにフォーカスしています。
CI/CDやJenkinsをさらに理解したい場合は、
構築した環境を元に以下のJenkinsの入門チュートリアルなどを実践してみると良いかと思います。
参考:サルでもわかるJenkins入門〜自動テスト環境を構築しよう