Dockerでwebサーバーを構築したい!!
記事を書いた経緯
昨年6月にDockerでwordpressのローカル開発環境を作ろうとして挫折。composeファイル使って適当にやったらサーバーはできたのだけど、Cyberduckでファイルを編集しようとしてパーミッションエラー(何をやっているんだか...)。昨年12月に仮想マシンにLinuxでwebサーバーを作ってみたけど所有者とかよく分からなくなった。
ネットで調べて色々やって見たけど、根本的な知識が足りない!まずは基本をしっかりやろう。
Dockerとは
Dockerとはコンテナ型仮想化ソフトのこと。仮想化とは実際のPCを用意せずに”仮想的にパソコンやサーバーを作れる仕組み”でDockerはそれを「コンテナ型」でする。仮想マシンとは違う。
仮想化にはVirtualBoxもあるけど、これは「ホスト型」というらしい。
詳しくはDockerドキュメントを参考にしてください。
Dockerの特徴
・ホストに左右されない実行環境(Docker Engineによる実行環境の標準化)
・DSL(Dockerfile)によるコンテナ構成やアプリケーション配置設定
・イメージのバージョン管理
・レイヤ構造をもつイメージフォーマット
・Dockerレジストリ
・プログラマブルな各種API
Docker/Kubernetes 実践コンテナ開発入門 (日本語) 単行本(ソフトカバー) – 2018/8/25
山田 明憲 (著)
Dockerの特徴が本に書いてあるけど、初心者には分からない言葉がいっぱい。用語を知らないと意味がよく分からないからまずは用語を調べる。
Docker Engine(エンジン)とは?
オープンソースによりコンテナ化する技術であり、コンテナを実行するために必要なプログラム(デーモン)。DockerではゲストOSを使わず、コンテナがこのDocker Engineを介して直接ホストOS上でアプリケーションを実行させることができる。
ゲストOSを必要としないためリソース(CPUやメモリ)が減り、仮想マシンと比べて起動や停止の動作が早く、また、データのサイズも小さくなるというメリットがある。
Dockerfileとは?
テキスト形式のドキュメントでDockerイメージを作り上げる手順を記述する。Dockerイメージの設計図となる。
Dockerの構成要素?
Docker イメージ
読み取り専用テンプレートで、Dockerコンテナを作成するために使用される。OSとして構成されたファイルシステムやアプリケーション、どのプロセスが実行されるかといった設定情報を含んだアーカイブのようなもの。イメージを構築することをイメージをビルドするという。レイヤ構造になっており、イメージに何らかの操作を行った時にイメージを再構築するのではなく、レイヤを追加するだけです。これによってDockerは軽量化されます。
Docker コンテナ
Dockerイメージを実行するときの実体です。コンテナが作成されるとイメージから具現化されたファイルシステム上でアプリケーションが実行される。ファイルシステムとアプリケーションが同梱されている箱のようなもの。
Docker レジストリ
Dockerイメージを保管・提供。必要に応じてコンテナをデプロイするために使用されるDockerイメージを格納する。
Docker Hub はクラウド上のレジストリ・サービスであり、アプリケーションやサービス・コンテナの構築と配信をする。
その他用語
ポートフォワーディング
ポートを紐づけること。-pオプションで行う。ポートフォワーディングされたDockerコンテナに外部からアクセスするときに使う。
コンテナオーケストレーションシステム
コンテナを効率よく配置したり、連携させる管理ツール。docker-compose(Docker社)、swarm(Docker社)、ECS (AWS)、Kubernetes(google社)などがある。
DockerはマルチOSに対応している
DockerはLinuxのカーネルに依存した技術です。Docker Engineのところで述べましたが、DockerはホストOSのカーネルを使用します。なのでホストOSはLinuxである必要があります。しかし、「Docker for Mac」や「Docker for Windows」を利用すると、MacOSやWindowsでもDockerを使えるようにできるのです。
仮想マシン型の仮想化技術を取り入れ、「Docker for Mac」や「Docker for Windows」は仮想マシン上でDocker専用の軽量なLinuxを動かしています。
Docker主要コマンド
#レジストリ関連#
$ Docker pull name //レジストリからイメージをダウンロード
$ Docker push name//レジストリにイメージをアップロード
$ Docker login //レジストリにログイン
$ Docker logout //レジストリからログアウト
#イメージ用コマンド#
$ Docker images //イメージの一覧
$ Docker rmi images //削除
$ Docker commit container //コンテナからイメージを作成
$ Docker build dockerfile //イメージをビルド
$ Docker tag image NEWimage //イメージにタグをつける
#コンテナの確認#
$ Docker ps //コンテナ一覧
#コンテナの作成・削除#
$ Docker run image //コンテナ作成(起動状態で)
$ Docker create image //コンテナの作成(停止状態で)
$ Docker rm container //コンテナ削除
#コンテナ用コマンド#
$ Docker start container //起動
$ Docker stop container //停止
$ Docker kill container //強制停止
$ Docker pause container //コンテナ上のプロセスを一時停止する
$ Docker unpause container //コンテナ上のプロセスを再開始する
【実践】Dockerとnginxを使ってwebサーバー
⒈Docker Desktop for Macのインストール
まず、Docker Hubでアカウントを作ってログインする。
https://hub.docker.com/editions/community/docker-ce-desktop-macからDocker.appをインストール
2.イメージをダウンロード(pull)
//nginxイメージを取得する
$ docker pull nginx:latest
または
$ docker pull nginx
//イメージが取得できているか確認
$ docker images
#結果 REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 2073e0bcb60e 2 weeks ago 127MB
docker pull nginxでレジストリからnginxのイメージをダウンロードしています。:latestはバージョン(最新)を指定しています。docker imagesでnginxが一覧に表示されれば取得が完了です。
⒊コンテナを作成(run)
//コンテナの作成
$ docker run -d -it -v /Users/[username]/docker/:/share -p 80:80 --name nginxserver nginx
//コンテナが起動できているか確認
$ docker container ls
#結果 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1b770b92e33f nginx "nginx -g 'daemon of…" 10 seconds ago Up 8 seconds 0.0.0.0:80->80/tcp nginxserver
docker runでイメージからコンテナを作成しますが、オプションで様々な設定をしています。
$ docker run [オプション] nginx
オプションの意味
-dバックグラウンドで実行
-itコンソールに結果を出力
-v /Users/username/docker:/shareディレクトリの共有。
コンテナの/shareディレクトリがホストの/Users/username/dockerディレクトリと共有される。
-p 80:80nginxのポート80にホストのポート80が紐づく
--name nginxserverコンテナ名をnginxserverにする
4.コンテナとの疎通の確認
$ curl localhost
nginxserverコンテナの80番ポートにアクセスしてhtmlを取得し表示されればコンテナとの疎通ができている。
0.0.0.0:80->80/tcp nginxserverコンテナのIPアドレスは0.0.0.0でこれがlocalhost
【エラー】curl: (7) Failed to connect to localhost port 80: Connection refused
-p 80:80ポート番号80にし、ホストとコンテナを一緒にすることで解決!
5.作成したコンテナのhtmlデータを書き換える
//bashでnginxserverの中に入る(bashとはシェルのこと)
$ docker exec -it nginxserver bash
//元々入っているhtmlディレクトリを削除
/# rm -rf /usr/share/nginx/html
//シンボリック・リンク(/usr/share/nginx/htmlを/shareにリンクする)
/# ln -s /share /usr/share/nginx/html
//コンテナから出る
/# exit
nginxserverコンテナ内に入り、/usr/share/nginx/htmlを削除。/shareディレクトリに/usr/share/nginx/htmlをリンクする。これによってホストの/Users/username/dockerディレクトリから/usr/share/nginx/htmlにアクセスできるようになった。
cd
cd /User/username/Docker
sudo vi index.html
#パスワードを求められるので入力する
//iでインサートモードにする
<h1>hello from host OS!</h1>
//escでインサートモード終了
:wq
//疎通の確認
curl localhost
http://localhost:80にアクセスすると”hello from host OS!”が表示されれば完了!
コンテナを削除する
//コンテナを停止
$ docker stop nginxserver
//コンテナを削除
$ docker rm nginxserver
//確認
$ docker container ls -a
6.Dockerfileで作る
$ vi Dockerfile
//iでインサートモードにする
FROM nginx:latest
MAINTAINER [任意の名前]
RUN rm -rf /usr/share/nginx/html
RUN ln -s /share /usr/share/nginx/html
//escでインサートモード終了
:wq
//イメージ(sample:1.0)を生成する:build
$ docker build -t sample:1.0 .
#ビルドが開始# Sending build context to Docker daemon 494.7MB ・ ・ Successfully built d7b0957fe17c Successfully tagged sample:1.0 #ビルドが完了#
$docker images
#結果 REPOSITORY TAG IMAGE ID CREATED SIZE username/sample 1.0 d7b0957fe17c 3 minutes ago 127MB sample 1.0 d7b0957fe17c 3 minutes ago 127MB
//Docker Hubに公開する:push
$ docker push [ユーザー名]/sample:1.0
Docker Hubにアクセスして公開できているか確認する。
【エラー】denied: requested access to the resource is denied
docker tag sample:1.0 [ユーザー名]/sample:1.0(DockerHubの)ユーザー名が間違っていた。
間違った名前のイメージを削除し、正しい名前を付け直したら解決した!
Docker Hubにログインできていない場合もエラーが出るのでログインする。docker login
感想
今回よかったことは、Dockerの用語とIT用語が分かるようになるとエラーの意味も分かるようになったこと!Dockerの構造を図にしてみたら理解が深まった。先日参加した【単発】Docker基礎を学ぶハンズオン!の助けもあり、Dockerがやっと分かってきた!
昨年失敗した原因も分かった!ポートフォワーディングを設定していなかったこと。vagrantの仮想マシンのLinuxでDockerを使おうとしていたことも初心者にとっては複雑で分かりにくくなった原因だろう。
コンテナの作り方は分かったので複数のコンテナを作成し、連携させれるように勉強を進めたいと思いました。