0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

<Vagrant+VirtualBox(CentOS7)+Docker>コンテナにnginxを入れて起動してみた

Last updated at Posted at 2021-03-09

TL;DR

今回の流れは大まかに以下です。

  1. VagrantでVirtualbox(CentOS7)を立ち上げ
  2. Shellスクリプトで、Dockerのプロビジョニング
  3. ホスト(ローカルのMac)からVMのCentOSに立ち上げたDockerコンテナのnginxにアクセス

VMマトリョーシカの初体験であります。

VagrantでVitrualboxにCentOS7を入れて立ち上げる

Vagrantfileは下記の内容で進めました。

# -*- mode: ruby -*-
# # vi: set ft=ruby :

## Version constraint
Vagrant.require_version ">= 1.3.5"

## Plugin constraint
unless Vagrant.has_plugin?("vagrant-hostsupdater")
  raise 'Missing plugin `vagrant-hostsupdater`! Install it by `vagrant plugin install vagrant-hostsupdater` command before vagrant up.'
end

# VM config
Vagrant.configure("2") do |config|
  config.ssh.insert_key = false
  config.vm.box = "centos/7"
  config.vm.box_version = "2004.01"
  config.vm.hostname = "vagrant-test.localhost.com"
  config.vm.network :private_network, ip: "192.168.0.1"
  config.vm.provider :virtualbox do |v|
      v.name = "centos7_vagrant_test"
      v.customize ["modifyvm", :id, "--memory", 2048]
      v.cpus = 1
      v.check_guest_additions = false
      v.functional_vboxsf     = false
      v.gui                   = false
  end

  # VM NFS
  config.vm.synced_folder ".", "/home/cwd/src", id: "home", :nfs => true, :mount_options => ['nolock,vers=3,udp,actimeo=2']

  # VM provisioning
  config.vm.provision "shell", run: "always", inline: <<-SHELL
    echo Hello, World
  SHELL
  config.vm.provision "shell", run: "always", :path => "./provision/local/scripts/docker-init.sh"

end

詳しい項目の詳細については、
こちらの記事も参考にご覧ください。
参考:「Vagrant+VirtualBox」ローカルで仮想環境を立ち上げてみる

「vagrant up」でvm立ち上げ

vagrant up

ポイント

  • Vagrantfileがあるディレクトリに移動(cd)し、vagrant upをする
  • vagrant-hostsupdaterを入れておくとmacの/etc/hostsを自動で更新設定してくれるので便利なのでその判定をする
    • vagrant haltvm停止後も、/etc/hostsから追加したホストを削除してくれる。
  • config.vm.provisionrun: "always"にしないと、provisioningは初回しか走らないので、必要に応じて設定する
  • :pathは、Vagrantfileがあるディレクトリを基準に相対パスで.shシェルスクリプトのファイルを指定する

Shellスクリプトで、Dockerのプロビジョニング

Shellスクリプトとは、コンピュータに対する命令をまとめて書くファイルで、
Linuxコマンドとか、自分でインストールしたコマンドとかで命令を書いて、バッチを作れるやつ。

試行錯誤を重ね、初めて自分で書いてみたものが下記。(なかなか大変だったこりゃ。)
(※何度も自分のローカルで動作確認したけど、もしかしたらエラー出て動かないかも・・・?)

# !/bin/bash

# Directory Definition
FIRST_OUTPUT=~/docker-compose
LAST_OUTPUT=/usr/local/bin/

# Install jq command if necessary
jq --version >/dev/null 2>&1
if [ $? -ne 0 ]; then
    sudo yum -y install epel-release
    sudo yum -y install jq --enablerepo=epel
fi

# Install wget command if necessary
wget --version
if [ $? -ne 0 ]; then
    sudo yum -y install wget
fi

# Download the latest Docker
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
wait
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
wait
sudo yum install -y docker-ce docker-ce-cli containerd.io
wait

# Download the latest docker compose
DOCKER_COMPOSE_LATEST_VERSION=$(curl -L https://api.github.com/repos/docker/compose/releases/latest | jq .name -r)
wget "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_LATEST_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -O ~/docker-compose
wait

# Make a directory & Move the installed docker-compose to the appropriate folder
sudo mkdir -p $LAST_OUTPUT
sudo mv ${FIRST_OUTPUT} ${LAST_OUTPUT}/docker-compose

# Change Owner & Mode for the Docker Compose
sudo chown root:root ${LAST_OUTPUT}/docker-compose
sudo chmod +x ${LAST_OUTPUT}/docker-compose

# Start Docker
sudo systemctl start docker
sudo systemctl status docker

# Run containers using docker-compose
cd /home/cwd/src/provision/local
sudo ${LAST_OUTPUT}/docker-compose up -d --remove-orphans

やっていることの解説

  • 最初にdocker-composeをインストールする場所を定義
  • CentOSはまっさらなPC状態で、使いたかったjqコマンドとwgetコマンドが入ってなかったので、最初にインストール
    • $?には直前のコマンドの実行結果が返ってきて、成功すると0が入るからそれで判定が可能。
    • jqコマンドは、JSONパースしてくれて、name属性だけを-rつまり""を取り除いて取得してくれるってやつ。
      • これでversionの名前がキレイにとれる。
  • 最新版のDockerをインストール
  • 最新版のDocker-composeをインストール:OSとハードウェア的に互換あるやつ
    • uname -sはkernel nameを出力してくれる
    • uname -mはmachine hardware nameを出力してくれる
  • インストールしたdocker-composeを仮置きしてたので、最終的に置きたい場所のためにフォルダ作成
    • そして移動
  • docker-composeのオーナーをrootに変更し、全ての人に実行権限だけを付与するように変更
  • Dockerをスタートして、一応statusなんかをコンソールに出しちゃって
  • docker-compose.ymlのあるディレクトリに移動し、docker-composeのバイナリファイルがあるディレクトリを指定しながら、docker-compose up
    • -dはバックグラウンド実行。いわゆるデーモンみたいな
    • --remove-orphansは、docker-compose.ymlにかかれていないサービスのコンテナを削除するってオプション

改善点

ってな感じで、自分で適当にバッチを書いてみたが、
もっとよく書けたり無駄があったり、するから改善の余地は多々ありそうw
あとは、ログ出力echoとか1>&2など、標準出力、標準エラー出力も意識した書き方をしないといけないと思っている。

Docker-compose.yml

version: "3.8"

services:
  web:
    image: nginx:latest
    # build: ./local/docker
    container_name: web
    ports:
      - 8080:80
    stdin_open: true
    tty: true
    privileged: true

最初Dockerfileを使う予定だったけど、一旦は難易度をさげて、通常のDocker Hubのimageを使う
tty: trueでコンテナが起動し続ける

いざ、nginxにアクセス!!

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                  NAMES
12exxe38xxx7   nginx:latest   "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:8080->80/tcp   web

0.0.0.0:8080->80/tcp
と立ち上がったので、
さっそく、ブラウザからアクセスしたい。

IPアドレスにポート番号でアクセス

Vagrantfileに設定したipアドレスにポート番号をつけて、
http://192.168.0.1:8080/
にアクセス!!!!!!!

スクリーンショット 2021-03-09 15.55.32.png
アクセスできた♪

ホストネームにポート番号でアクセス

次に、ホストネームでアクセスする!!!
http://vagrant-test.localhost.com:8080/
スクリーンショット 2021-03-09 15.55.58.png

できた。。
ホスト名にポートつけるのかっこ悪いしなんだか気持ち悪いなあ、、、
でもまだ解消方法が分からないので次回挑戦。

ポート番号として 80 番を使用する場合だけは例外で、ポート番号を省略した場合は 80 番が指定されたものとして扱われます。そのため本来であれば「http://www.example.com:80/ 」のようにアクセスする代わりに「http://www.example.com/ 」のようにポート番号を省略してアクセスすることができます。
参考元:80番以外のポート番号を使用した場合のWebサーバへのアクセス

ここまでくるのに、1週間以上はかかったなあ。
大変でしたが、つながると気持ちいいですね!!

ハマったポイント

Vagrantfile

フォルダ階層につまづき・・・

config.vm.synced_folderで、どうやってフォルダがマウントされるかという実感が持てず、
そもそもマウントされていないんじゃないかってところで何時間も調査したが、
単純にvagrantのvirtualbox内の階層を理解していなかっただけだった。

vagrant ssh

で、ログインしたときに最初にたどり着くディレクトリが
/home/vagrant
で、そこからスタートするのかとかマジで知らんしって状態だったんだけど、
自分が指定したのは
config.vm.synced_folder ".", "/home/cwd/src",

つまり、
/home/cwd/src/
であって、
ログイン後に一回cd ../してls -laをすれば、自分の階層を見つけられたのだった。
ど素人すぎて、階層の蟻地獄にハマりました。

Docker-compose

アクセスがリセットされてしまう問題。

curl: (56) Recv failure: Connection reset by peer

これでずっと苦しむ。
ymlファイルに、以下のプロパティを設定したら、上記エラーがでて、nginxがhtmlを返さなくなってしまった。

command: tail -f /dev/null
user: $USER_ID:$GROUP_ID

原因が完全には理解していないものの、
おそらく
tail -f /dev/nullすると常にコマンドが実行状態となり、忙しくて返って来なくなる
userはユーザー権限の問題と衝突してダメ
という予想です。

sudo docker exec -it web /bin/bash
curl localhost:8080

このコマンドで、dockerコンテナに入り込んで、コンテナのnginxが起動してるか確認ができる。

Nginxのdefault.conf

無駄にdefault.confを理解もしないでいじり倒してしまった

defalt.confの設定も、よくわからないネットで拾ってきたものをマウントさせて使ってしまったから、ダメだった。
nginxのインストールしたてホヤホヤのものをそのまま使えば、よかったのに。

curl: (56) Recv failure: Connection reset by peer

が出続けた。

listenの設定がすごく大事だった。

# default.confの一部
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

リクエスト&レスポンスの流れ

  1. まずは、localhostは127.0.0.1に解決される。
  2. 次に、Port Forwardingがなされ、127.0.0.1:8080 -> 172.17.0.x:80
    • 「ホストの全インターフェースの8080ポート宛通信をコンテナの80ポートに転送する」
  3. 172.17.0.x:8000 -x-> 127.0.0.1:8000
    • ホストマシンからのリクエストがコンテナのIPアドレス 172.17.0.xの80ポートに届いたが一方で、アプリ側は 127.0.0.1:8080でしかlistenしておらず、172.17.0.x:80ではListenしてないみたいになっていた。
  4. 0.0.0.0でサーバを建てると、そのホスト(今回の場合、コンテナ)が持つ全てのインターフェースでLISTENできる

まとめ

VMマトリョーシカは、泥沼でした。
深海のような水圧で、押しつぶされながらも、なんとか呼吸し、水面に脱出できました。

∈( 'Θ' )∋ .。○⚪︎

以上、ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?