case-kの備忘録

備忘録です。

Docker環境構築入門してみた

Dockerを実際に触ったことがなかったので、Dockerの概要や実際の扱い方について備忘録も兼ねて記事にしてみました。

追記:
本記事ではVM環境をMAC上に構築し、VM環境の上でDockerを使いましたが、VM環境を構築する方法だと、構築にリソースを使ってしまうため、
Mac上で直接Docker環境を作る方がこのましいです。Dockerはプロセスであるため、VMと比較するとリソースを使わずにすみます。

本記事の目的

・Dockerの概要を理解すること
・Docker環境を構築し実業務に活かせるようになること

Dockerとは

Dockerとは異なるOS環境でも同じ環境を構築するために用いられるツールです。実業務で本番環境と同一の環境をローカルPCで構築したくても、OS[MAC/Windows]の違い、アプリケーション、データ、ライブラリなど同じ環境を構築するのは非常に手間です。また、構築した環境が誤っていた場合はローカルで動くのに、本番で動かないことも考えられます。Dockerを使えば異なる環境でも全く同じ開発環境を構築することが可能となるので、環境構築に当てていた時間を、本来時間を割きたいアプリの開発や分析業務に当てることができます。

Docker誕生背景

Dockerが誕生する前にもホストマシン[MAC/Windowsなど]に仮想環境を構築するための方法はありました。Vagrantなどの「ホスト型」はホストマシン[MAC]に別のOS環境をインストールし、ホストマシンとは異なるOS環境を構築が可能で、環境構築、削除を容易に行えるようになりました。便利にはなりましたが、この方法だと目的のアプリケーションとは関係のないサービスも多数動作してしまい、リソースを膨大に消費してしまいました。この課題を解決するための方法として「コンテナ型」と呼ばれる新しい手法が生まれました。「コンテナ型」とはLinux(OS)カーネル(OSの中核ソフトウェア)がもつコンテナ機能を使い、実行環境を他のプロセスから隔離し動作させる技術です。必要としているリソースのみ活用できるので、リソースの消費を抑制することができます。また「ホスト型」では仮想環境は構築できるものの、本番環境とのOSの違いや、アプリケーションやデータ共有など全く同一の環境を構築することはできませんでした。「コンテナ型」であるDockerは同一の環境を数秒で作ることができます。リソースの消費を抑え、異なる環境でも同じ環境を素早く作ることを目的にDockerは誕生しました。

仮想環境構築 [Vagrant/VirtualBox]

まず、ローカルPCに仮想環境を構築し、その中でDocker環境を構築したいと思います。MACから直接Docker環境構築も可能ではありますが、PCに直接環境構築に必要なライブラリなどをインストールすることは極力避けるべきです。誤った操作やライブラリをインストールしてしまうと修正が非常に手間だからです。なので影響範囲を構築環境内に留める為にも、仮想環境をVagrantで構築し、仮想環境内でDocker環境を構築します。まずはVirtualBoxをインストールし、Vagrantを使って仮想環境を作ります。

Vagrant環境構築の流れは以下の通りです。

1. install Vagrant & VirtualBox 
2. vagrant init 
3. vagrant up 
4. vagrant ssh
install Vagrant & VirtualBox

まずはVirtualBoxVagrantをインストールします。
VirtualBox:仮想環境を作るソフトです。MAC OS上に別のOS[ubuntu]を活用した環境を構築が可能です。
VagrantVirtualBox を操作するツールとなります。vagrantコマンドを活用し仮想環境の構築や削除が可能です。
以下よりVagrantをインストールして下さい。
https://www.vagrantup.com/
f:id:casekblog:20180930193428p:plain:w300
次にVirtualBoxをインストールします。以下のサイトよりubuntuのtrusty64ビットを選びコピーして下さい。
http://www.vagrantbox.es/
f:id:casekblog:20181003233349p:plain:w400
以下のコマンドを実行し、ホストマシン[MAC]にVirtualBoxを追加して下さい。

#  Add VirtualBox
$ vagant box add trusty64 https://github.com/sepetrov/trusty64/releases/download/v0.0.5/trusty64.box

# Check VirtualBox
$ vagrant box list
trusty64 (virtualbox, 0)
vagrant init

初期化処理を行い仮想環境の設定ファイルを作成・編集します。
初期化処理には実行するVirtualBoxを指定します。今回は追加したtrusty64を指定します。

# 初期化
$ vagrant init trusty64

# 編集:コメントアウトを外しIPアドレスを以下にします。
$ vi Vagrantfile  [i + esc + :wq!]

# Out
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.55.44"

f:id:casekblog:20181003233859p:plain:w400

vagrant up

Vagrantを起動し、仮想環境を構築します。

#  起動
$ vagrant up
vagrant ssh

仮想環境を起動できたのでSSHでログインしてみます。

$ vagrant ssh

# Out
Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 3.13.0-158-generic x86_64)
・・・

Docker環境構築

Vagarant環境にログインできたので、いよいよ構築したVagrant環境内でDocker環境を構築します。
流れは以下のようになります。

1. Docker install 
2. Docker Image
3. Docker Pull
4. Docker Container
5. Create Image from Container 
6. Commit Created Image
7. Docker Build
8. Create Web Server Dockerfile
9. Docker Push

個人的にDockerはGit扱いに非常に類似している印象を受けます。Docker HUBと呼ばれるDocker Image(Docker環境構築の設計図)を管理している箇所からDocker PullしImageを取得します。Imageは環境構築を行うための設計図です。起動すると、設計図に記載した環境[ライブラリ、アプリ、データベースなど]が作られます。この設計図に変更を加えたい場合には設計図を修正し、Docker CommitしDocker HUBにPushします。Docker HUBではリポジトリで管理しているためいつでもそのデータを獲得することが可能です。
f:id:casekblog:20180930191939p:plain

Docker install

まずはDockerをinstallします。以下のコマンドを実行して下さい。
※ Docker のインストールの詳細は以下を確認してみて下さい。
Get Docker CE for Ubuntu | Docker Documentation

# ubuntu
$ sudo apt-get update
$ sudo apt-get install docker.io

#Out
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:

※  docker-ceではなくdocker.ioです。ちょっとつまづいたのでメモしときます。

Docker Image

まずはDocker HUB[旧 Docker Index]からImageを取得します。
※ Docker HUB [旧Docker index]
Docker Imageを管理するリポジトリです。Git でプログラムを管理するように、Docker HUBではDocker Imageを管理します。
※ Docker Image
仮想環境を作る設定ファイルです。Docker Imageから異なる環境でも全く同じ環境構築が可能です。
Imageは Docker コンテナの作成時に利用されます。プログラミングで言う所のクラス[設計図]に該当します。Docker PullよりDocker HubからDocker Imageを取得します。https://hub.docker.com/

Docker Pull

それではDocker PullでDocker HubよりDocker Imageを取得したいと思います。

# Docker Image一覧確認
$ sudo docker search centos | more

# Docker Pull
$ sudo docker pull centos

# Out
latest: Pulling from centos
675ac122cafb: Pull complete
a4875ffe6057: Pull complete
c5507be714a7: Pull complete
Digest: sha256:5d91c5535c41fd1bb48d40581a2c8b53d38fc2eb26df774556b53c5a0bd4d44e
Status: Downloaded newer image for centos:latest

TipsとしてImageの操作方法のコマンドも記載しておきます。

# Check Docker Image
$ sudo docker images

# Out
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              latest              c5507be714a7        7 weeks ago         199.7 MB

# Docker Image 詳細確認
$ sudo docker inspect [IMAGE ID]
[{
    "Architecture": "amd64",
    "Author": "",
    "Comment": "",
    "Config": {
 ・・・・
# Docker Image 削除
$ sudo docker [image id]
Docker Container

Imageが作れたので、いよいよContainer起動してみようと思います。
Docker Containerとは、設定ファイル[Docker Image]から作られた仮想環境です。Containerはアプリケーションの実行に必要な全てが含まれています。環境構築に必要なライブラリなどが入った状態の環境を作ることが可能です。プログライミングでいうクラス[設計図]がDocker Imageに該当し、クラスから作るインスタンス[実体]がDocker Containerに該当します。まず、試しにコンテナを起動して「Hello World」と表示させます。コンテナの起動は「Docker Run」で行います。

# Container起動とジョブ実行
$ sudo docker run centos echo "Hello world"
Hello world

実行したジョブの内容を確認してみます。以下のコマンドを実行すると、実行結果を確認できます。実行したジョブにはCONTAINER IDが割り振られています。
このIDを活用してCONTAINER の操作を行うことができます。

# 確認 
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                     PORTS               NAMES
8c96f399eac6        centos:latest       "echo 'Hello world'"   3 minutes ago       Exited (0) 3 minutes ago                       modest_kowalevski

以下Containerの操作方法です。

# delete container 
$sudo docker rm [CONTAINER ID]

# run per 3 second
$sudo docker run -d centos free -s 3

# check logs
$sudo docker logs [CONTAINER ID]

# stop
$sudo docker kill [CONTAINER ID]

# start 
$sudo docker start [CONTAINER ID]
Create Image from Container

Containerから新しくImageを作りたいと思います。Containerに入り、hello.txtファイルを作ります。以下を実行して下さい。

# コンテナに編集モード[-i]ターミナル[-t]で入ります。
vagrant@vagrant-ubuntu-trusty-64:~$ sudo docker run -i -t centos /bin/bash
[root@a165524f1e8b /]# touch hello.txt
[root@a165524f1e8b /]# ls -ltr
# Out
・・・・
-rw-r--r--  1 root root     0 Oct  1 11:00 hello.txt
[root@a165524f1e8b /]# exit

# Check Container
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
a165524f1e8b        centos:latest       "/bin/bash"         3 minutes ago       Exited (0) 2 minutes ago                       jovial_heisenberg

Container作成とImageを作ることができました。

Commit Created Image

Container内に作成したファイルをCommitすることで、Pushできるようにし、別環境からImageの取得を実現します。

# Create Image
$ sudo docker commit  [CONTAINER ID] hoge/hello[Image name]

# Commit
$ sudo docker commit a165524f1e8b hoge/hello
86cf795d5441dd7fa20cb3ad4707a489e601a329e08964f27cf9d4ed4c6fc331

# Check Images
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hoge/hello          latest              86cf795d5441        8 seconds ago       199.7 MB
centos              latest              c5507be714a7        7 weeks ago         199.7 MB

Hello Textがあるか確認します。

$ sudo docker run -i -t hoge/hello /bin/bash

# Check Container
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
734bcb8059a2        hoge/hello:latest   "/bin/bash"         22 seconds ago      Exited (0) 5 seconds ago                       elegant_heisenberg
a165524f1e8b        centos:latest       "/bin/bash"         10 minutes ago      Exited (0) 9 minutes ago                       jovial_heisenberg
Docker Build

これまでImageをPullしContainerを起動し、起動したContainerを更新しCommitしました。
Dockerにはこの一連の処理を自動化するスクリプトが用意されており、Docker Buildといいます。
Buildするためには実行内容を記載した「Dockerfile」を活用します。まずはDockerfileを作ります。以下のファイルを作成して下さい。

$ vi Dockerfile[i+esc+:wq!]

# Image 
FROM centos
# Who wrote this file
MAINTAINER Gen Hoge <hoge@gmail.com>
# Run:buildするときに実行される
RUN echo "now building"
# CMD:Runするときに実行される
CMD  ["echo", "now running"]

Dockerfileを作成できたので、Docker Buildします。

# Docker Build 
$sudo docker build -t hoge/echo .

# Out
Sending build context to Docker daemon 13.31 kB
Sending build context to Docker daemon
・・・・

BuildしたImageとContainerを確認します。

# Check Images
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hoge/echo           latest              122d61f3564b        15 seconds ago      199.7 MB
hoge/hello          latest              86cf795d5441        22 minutes ago      199.7 MB
centos              latest              c5507be714a7        7 weeks ago         199.7 MB

# Run Container 
$ sudo docker run hoge/echo
now running

# Check Container
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                      PORTS               NAMES
ae50b955f413        hoge/echo:latest    "echo 'now running'"   28 seconds ago      Exited (0) 28 seconds ago                       modest_franklin
734bcb8059a2        hoge/hello:latest   "/bin/bash"            22 minutes ago      Exited (0) 22 minutes ago                       elegant_heisenberg
a165524f1e8b        centos:latest       "/bin/bash"            32 minutes ago      Exited (0) 31 minutes ago                       jovial_heisenberg

正しくBuildできたようです。

Create Web Server Dockerfile

少し実践的な処理を行いたいと思います。DockerfileにWEBサーバをインストールしブラウザから確認してみましょう。

$ vi Dockerfile

# Out
FROM centos:centos6
MAINTAINER hoge <hoge@gmail.com>
RUN yum install -y httpd
COPY index.html /var/www/html/
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

※ FROM:PULLするイメージを指定します。
現在[2018年9月]FROM centos と記述すると CentOS 7 系がインストールされ、httpd のインストールに失敗してしまうため6系をインストールします。
※ ADD:サーバ環境のファイルをイメージに取り込む
※ CMD:RUN[コンテナ起動]で実行するコマンド
※ EXPOSE 80:HTTPで使うポート番号
Docker Image にコピーするファイルを作ります。Container起動後ブラウザからHTMLに記載した内容が表示されるか確認します。

vi index.html

# Out
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>helloworld</title>
</head>
<body>
    <h1>helloworld!</h1>
</body>
</html>

準備ができましたので、実際にビルドしてみたいと思います。最終的にDocker HUBにPUSHをするので以下の形式でビルドを実施して下さい。
$sudo docker build -t [Docker user name]/[Repository] .

# Docker build
$ sudo docker build -t hoge/httpd .

Container から作成したImageを起動しブラウザから確認してみます。
ホストのポート8080をコンテナのポート80リダイレクトさせます。

$ sudo docker run -p 8080:80 -d hoge/httpd

#Out
9555cec58b1b2ac1c75c22857b7ce583d7e499d0eadcc29d390e2c407307d1a9

※ -d:Back Groundで走らすコマンド
うまくできたかブラウザから確認してみたいと思います。
Vagrantfileに記載したIPアドレスにポート「:8080」を指定してみます。
http://192.168.55.44:8080/
f:id:casekblog:20181003215923p:plain:w300

Docker Push

外部環境でも同様の環境を作れるように、作成したDocker ImageをDocker HUBにPushします。
事前にDoker HUBのアカウントとリボジトリが必要となりますので準備して下さい。

$ sudo docker push hoge/httpd

以下より登録してください。
https://hub.docker.com/
アカウントの準備が整いましたら、コマンドラインでDockerにログインしたいと思います。

$ sudo docker login
Username: ?????
Password:?????
Email:??????

ログインが成功するとPUSHできるようになります。
作成したImageをPUSHするめには以下の形式に従う必要があります。
$ sudo docker push [Repository]:[Tag]
作成したImageのRepositoryとTagを確認してPushします。

# PUSH
$ sudo docker push hoge/httpd:latest
The push refers to a repository [hoge/httpd] (len: 1)
5f6020d11dc4: Image successfully pushed

PUSHが無事成功したら実際にDocker HUBでRepositoryを確認してみましょう。

冒頭にも書きましたが、作成したImageを取得するにはPullして下さい。

$ sudo docker pull hoge/httpd

■ 参考情報
いまさらDockerに入門したので分かりやすくまとめます - Qiita
Dockerについてなるべくわかりやすく説明する - Qiita
Dockerfileを書くときに気をつけていること10選 - Qiita
「Vagrant」と「Virtual Box」の違い - Qiita
https://dotinstall.com/lessons/basic_docker/27704
https://dotinstall.com/lessons/basic_localdev_mac_v2/38501
Dockerイメージの理解とコンテナのライフサイクル
http://docs.docker.jp/engine/introduction/understanding-docker.html
原理原則で理解するDocker - Qiita
Part 1:概要説明とセットアップ — Docker-docs-ja 17.06.Beta ドキュメント
https://show-go.jp/top/2017/10/30/dockear/
Dockerhubへの初プッシュ - Qiita
VirtualBox とは?
dockerとvagrantの違い言える?新人エンジニアでも分かった気になれる俺流まとめ - This is a Pen
ホスト型とハイパーバイザー型の違いは何?VMware vSphere Hypervisor の概要 | Think IT(シンクイット)
【仮想化】コンテナ型仮想化とは・ホスト型やハイパーバイザ型との違い | ゆとり鳥日記
dockerとvagrantの違い言える?新人エンジニアでも分かった気になれる俺流まとめ - This is a Pen
VagrantとDockerについて名前しか知らなかったので試した - Qiita
第1回 Dockerとは:超入門Docker - @IT
注目を浴びる「Dockerコンテナ」、従来の仮想化と何が違うのか? | 新野淳一コラム | 東京エレクトロンデバイス株式会社


# Dockerfile
Docker入門(第四回)~Dockerfileについて~ | さくらのナレッジ
効率的に安全な Dockerfile を作るには - Qiita