いづいづブログ

アジャイルコーチになりたい札幌在住SEです。アジャイル札幌スタッフ&ScrumFestSapporo実行委員。Like:パクチー/激辛/牡蠣/猫/初期仏教

NginxでHello,World

f:id:izumii-19:20190428123747p:plain:w300

debian環境にNginxのインストールまでがうまくいったので、次は任意のhtmlファイルを配置してそれを表示させるようにしてみます。

実際にやってみるにあたっては設定ファイルの意味などをだいぶ調べたりしているのですが、このブログ自体はかなり雑に書いているので同じことをやりたい人の参考にあまりならないかもしれませんがお許しください。俺メモに近いです。

環境

さくらのVPSに作ったDebian9(stretch)

設定ファイルの場所

パッケージシステムからNginxをインストールすると、設定ファイルは通常ここにできる。このファイルを開いて中を見てみる。

/etc/nginx/nginx.conf

設定ファイルの中身

f:id:izumii-19:20190428114425p:plain
nginx.conf

とにかく今表示されているindex.htmlファイルがどこにあるかを知りたいのだからが、ファイル内にはとくにindex.htmlに関する記述はないように見える。なのでこの設定ファイルの中身について理解すべく色々調べてみた。 設定ファイルは、Nginxのモジュールのカテゴリごとに分けて記述する必要があり、大きく分けて4つのカテゴリがある。

  • coreモジュール
  • eventモジュール
  • httpモジュール
  • mailモジュール(上の画像にはない)

eventモジュールの設定はevents{}、httpモジュールの設定はhttp{}内に書いてある。(coreモジュールの設定は{}でくくらず先頭にまとめて書くようだ。)

ここでhttp{}内の下の方に以下のような記述がある。

include /etc/nginx/conf.d/*.conf; 

include ディレクティブにファイル名を記述することで、指定したファイルに書かれた設定を読み込むことができる。

ここでは/etc/nginx/conf.dフォルダ以下にあるすべての.confファイルを読み込むという意味になる。

なので、/etc/nginx/conf.dフォルダ以下にある.confファイルの中身を確認してみる。

default.conf

/etc/nginx/conf.dフォルダ以下にあるdefault.confファイルを開く。

f:id:izumii-19:20190428121511p:plain
default.conf

サーバーごとの設定(server{}セクション)が書かれているっぽい。 このserver{}セクション内にlocation{}セクションが存在する。そしてrootの場所とindex.htmlの設定が書かれている。

server {
 〜 略 〜
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
 〜 略 〜
}

locationの中身についてはいろいろ調べてそこそこ大変だったが、調べたことを全部書くと膨大な量になるので省略。 以下のサイトが参考になったので、default.confファイルの記述の中身についてはここを読むと良い。

nginx連載3回目: nginxの設定、その1 - インフラエンジニアway - Powered by HEARTBEATS

nginx連載4回目: nginxの設定、その2 - バーチャルサーバの設定 - インフラエンジニアway - Powered by HEARTBEATS

nginx連載5回目: nginxの設定、その3 - locationディレクティブ - インフラエンジニアway - Powered by HEARTBEATS

で結論としてはlocationの設定をURIのパス毎に分けて書くことで、おのおの任意のページを表示できる。 なので、既存の locationセクションのしたにもう1つ任意のindex.html を表示するためのlocationの設定を、既存のlocationの設定の下に追加する。

location /reiwa { 
    root   /usr/share/nginx/html/reiwa; 
    index  index.html index.htm; 
} 

表示

アクセスしてみたら表示された。

f:id:izumii-19:20190428123429p:plain
hello,worldならぬ「Hello reiwa!!」

Nginxをインストール

f:id:izumii-19:20190428123747p:plain

年間契約してからずっと眠っていたさくらのレンタルサーバDebian)にNginxをインストールして、Webサーバを構築してみます。

環境

さくらのVPSに作ったDebian9(stretch)

インストール

nginx: Linux packagesにインストール手順が書いているのでこの通りにやる。

1.先にGnuPGというツールのインストールが必要らしいので入れる。この通りに実行。

$ sudo apt install curl gnupg2 ca-certificates lsb-release

2.今回は安定版をインストールするので、安定版のパッケージをリポジトリに追加するための設定を行う。この通りに実行。

$ echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

3.公式のNginx署名鍵をインポートする。この通りに実行。

$ curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -

4.鍵が正しく登録されていることを確認。この通りに実行。

$ sudo apt-key fingerprint ABF5BD827BD9BF62

f:id:izumii-19:20190427105420p:plain
鍵が登録されている

5.リポジトリを更新して、Nginxをインストールする。

$ sudo apt update
$ sudo apt install nginx

ちなみにアンインストールをする場合のコマンドは apt remove nginx

6.インストールできたか確認

$ sudo nginx -v
nginx version: nginx/1.10.3

起動確認

状態を確認する。[Active]がinactive(dead)になっているので停止中。

 $ sudo systemctl status nginx

f:id:izumii-19:20190427141754p:plain

f:id:izumii-19:20190427141952p:plain

Nginxを起動する。[Active]がactive(running)になっているので起動できた。どれどれ確認。 「Welcome to nginx!」と表示されていればOK!

$ sudo /etc/init.d/nginx start
$ sudo systemctl status nginx

f:id:izumii-19:20190427142226p:plain
起動した

f:id:izumii-19:20190427142338p:plain
Welcome to nginx!

ちなみに停止するときはこれ。

$ sudo /etc/init.d/nginx stop

おまけ

実は最初に起動したときはこんなエラーがでた。「80番ポートは既に使われている」と言われてしまっている。

f:id:izumii-19:20190501090437p:plain
80番ポートでエラーが発生しているっぽい

以下のサイトの手順で、プロセスをkill してからもう一度起動したらうまくいった。

easyramble.com

Debian9でsudoコマンドを使えるようにする

f:id:izumii-19:20190427094311p:plain

eginxをインストールする前に大事なことを忘れてました。

これまで学習するときには、さくらのレンタルサーバーのお試し期間を利用して無料で使っていたのですが、今後環境を構築していくとやったことを残しておきたくなるので年間契約に変更しました。 そのときにこれまで使っていたサーバーを残すのではなく新規契約にしたので、今OSすら入っていない状態なのでした。

そんなわけでDebianのインストールから地道にやり直しているのですが、Debian9ではsudoがデフォルトで使えるようになっているわけではないので、sudoの設定も行います。

f:id:izumii-19:20190427091435p:plain
"izumii19"はsudoが使えるユーザーではないと言われる

インストール

rootユーザーに変更してからsudoのインストールを行う。

$ su -
# apt install sudo

ユーザーを追加

rootユーザーのままsudoの設定ファイルを開く。以下のコマンドを実行。

# visudo

”#Allow members of group sudo to execute any command”の下にsudoを使いたいユーザーを追加する。*1

username ALL=(ALL:ALL)ALL

f:id:izumii-19:20190427092440p:plain
ユーザーを追加

nanoというテキストエディタで起動していた場合、Ctrl+oのあとにEnterを押して保存、Ctrl+xで終了。

ここまでで必要な準備はおしまい。rootユーザーを終了する。

# exit

sudoコマンド実行

sudoが使えるようになりました。

f:id:izumii-19:20190427094831p:plain
実行できるようになりました

参考サイト

Debianでsudoが使えなかったことのメモ - pogin’s blog

*1:あ、タブのインデントが揃ってない

GWの学習予定

f:id:izumii-19:20190426135245p:plain:w400

GWに勉強したいことまとめ。娘'sは合宿で家を空けるし家事は少なくてすむし、そんなに無理な予定ではないはず…!

チェリー本はAmazonで注文しているので届いたら中身をみてから予定を立てようかな。

4月

nginx

  1. nginxをさくらのDebian環境にインストールして、なんかのhtmlをおいて、ブラウザからアクセスして表示させる Done!
  2. VirtualHostの機能を使って、複数のドメインのサイトを立ち上げてみる Done!
  3. SSLに対応したサイトをつくる(Hello,Worldが表示される程度) Done!

vue.js

  1. vue.jsでHello,Worldを表示させる Done!

5月

Ruby

  1. 環境構築 Done!
  2. チェリー本にそって自習 Doing

Vue.jsの開発環境構築

f:id:izumii-19:20190414231959p:plain:w400

【注意】
最新のvue CLI バージョンは3系です*1が この環境構築はvue CLI 2系での手順です。

2系と3系ではパッケージ名が変わっていたり*2、 プロジェクトの作成がコマンド以外にvue UIで可能になるなどの違いがありますのでご注意ください。

JavaScriptもNode.jsもなにも知らない人が、とりあえずVue.jsで"Hello World"を出力するところまでをやってみようと思います。

なにはともあれ環境構築から。

目的

JavaScriptやVue.jsやNode.jsについて何も知らなくても環境構築できること。 なのであまり細かい設定についてはふれず、とにかく起動できるところまでをゴールとします。

環境

必要なインストールまとめ

Qiitaなど見てみるといきなりVue.jsだけ入れればいいってもんでもないようなので、環境構築に必要なものをざっくり整理してみた。

  1. nodebrewをインストール
  2. Node.jsをインストール
  3. vue-cliをインストール
  4. Vue Devtoolsをインストール

環境構築

1. nodebrewをインストール

nodebrewはNode.jsのバージョン管理ツール。Node.jsをインストールするのに必要なので最初に入れる。

$ brew install nodebrew

2. Node.jsをインストール

インストールしたnodebrewを使ってNode.jsの最新版をインストールする。 Vue.jsをインストールするためにnpmを使用するのだが、npmはNode.jsをインストールすると使用可能になる。

npmはNode Package Managerの略で、Node.js用に作られたライブラリやパッケージを管理する為のパッケージマネージャー。

$ nodebrew install-binary latest

最後の引数は[stable:安定版][latest:最新版]です。

なんかエラーがでた。

Fetching: https://nodejs.org/dist/v11.14.0/node-v11.14.0-darwin-x64.tar.gz
Warning: Failed to create the file 
Warning: /Users/izumi/.nodebrew/src/v11.14.0/node-v11.14.0-darwin-x64.tar.gz: 
Warning: No such file or directory

No such file or directoryって言われている。

このエラーは ~/.nodebrew/src のディレクトリが必要なんだけど存在しないときに出るということなので、~/.nodebrew/srcを作ることで解決できる。*3

$ mkdir -p ~/.nodebrew/src

これを実行してからあらためてNode.jsのインストールを実行したらうまくいった。

インストールされたNode.jsのバージョンを確認。v11.14.0がインストールされているのがわかる。

$ nodebrew ls
v11.14.0

使いたいNode.jsのバージョンをインストールしたバージョンのリストから選ぶ。 今回はv11.14.0しか入れていないのでv11.14.0を選ぶ。

nodebrew use v11.14.0

3. PATHを通す

以下を実行して~/.bash_profileを開く。ファイルがなければ$ touch .bash_profileを実行して作成する。

$ vi ~/.bash_profile

以下を追加する。

export PATH=$HOME/.nodebrew/current/bin:$PATH

設定ファイルを読み直す。

exec $SHELL -l

4. ここまで確認

各バージョンを確認し、バージョンが表示されればOK。

$ node -v
v11.14.0
$ npm -v
6.7.0

5. vue-cliをインストール

vue-cli*4コマンドラインを使ってvue.jsの開発を支援してくれるツール。vue-cliをインストールする時にwebpackも一緒にインストールされる。

Node.jsをインストールするとnpmが使えるようになるので、npmコマンドを使用してvue-cliをインストールする。

$ npm install -g vue-cli

ここまでできれば環境構築に必要な作業は完了。

6. Vue.js Devtoolsをインストール(推奨)

Vue.js Devtoolsは、Vue.jsの開発をサポートする Chromeブラウザの拡張機能。これを導入するとconsoleを開かなくてもdataの中身などを確認することができデバッグなどが簡単になって便利なので、公式でも入れることを推奨している。

ここにアクセスして追加する。

7.プロジェクトを作成する

ここからは実際に動かすための手順。

今回は"helloworld"というプロジェクトを作成する。initコマンドの引数は以下の通り。

vue init [テンプレート名] [プロジェクト名]

テンプレートは色々種類がある*5が、どんな時に何を使うのかわかっていないので一番無難そうな「webpack」を選択した。

vue init webpack helloworld

いろいろ聞かれるがとりあえず今回はすべてenterキーで進めることにした。

8.起動する

プロジェクトの作成が終わるとこんなかんじのことを言われる。

# Project initialization finished!
# ========================

To get started:

  cd test
  npm run dev

指示通りtestディレクトリに移動してnpm run devコマンドをたたきサービスを実行。 すると、以下のようなメッセージが表示されVue.jsのWebサーバが起動する。

 I  Your application is running here: http://localhost:8080

http://localhost:8080にアクセスしてみる。

f:id:izumii-19:20190414231227p:plain:w500

これが表示されれば環境構築は成功!

ちなみにサービスを終了はctrl + c

次回は"Hello World"を出力してみます。

参考サイト

Node.js / npm をインストール (Mac環境) - Qiita

npm入門 - Qiita

Vue.jsの開発環境を構築してみる - Qiita

*1:2020/2/9時点

*2:2系は「vue-cli」ですが3系から「@vue/cli」になっています。

*3:https://qiita.com/ucan-lab/items/517ee13a2f8769ab866c

*4:cli = Commnad Line Interfaceの略

*5:https://github.com/vuejs-templates

fetchとpullと、リモート追跡ブランチ

f:id:izumii-19:20190410135422p:plain

gitを使っているとcommit、push、pull、mergeあたりのコマンドはよく使うのでだいぶ理解できていると思うんですが、fetchについてはいまだに理解しきれていなかったのでfetchと向き合ってみることにしました。

私が理解したいことは以下の2点です。

  1. fetchとはなにか
  2. fetchとpullの違い

リモート追跡ブランチ

まず、fetchを理解する上で欠かせないのが「リモート追跡ブランチ」の存在。

ざっくりいうとローカル側に存在する「origin/master」というやつがリモート追跡ブランチ*1で、その名の通りリモートリポジトリの変更を追いかけているブランチのこと。

ちなみに"origin/master"はリモートリポジトリに存在するmasterブランチの追跡ブランチであり、例えばtestというブランチの追跡ブランチの場合は"origin/test"になる*2

f:id:izumii-19:20190410125212p:plain

fetch

fetchをするとリモート追跡ブランチにリモートリポジトリにあるブランチの最新状態が更新される。リモート追跡ブランチが更新されるだけで、ローカルの作業ブランチは影響を受けない。ここがpullと異なる点。

ちなみにfetchは"取ってくる"という意味らしい。

$ git fetch

merge

fetchはリモート追跡ブランチを更新するだけでありローカルの作業ブランチは影響を受けないため、作業ブランチに変更を取り込むにはmergeする必要がある。

$ git merge origin/master

pull

fetchとmergeを一度にやる方法。つまり作業ブランチにもリモートリポジトリの最新状態が即座に反映される。pull = fetch + merge。

$ git pull

まとめ

ローカルには作業ブランチとリモート追跡ブランチという2種類のブランチがあり、リモート追跡ブランチはリモートの変更を管理するブランチ。リモート追跡ブランチだけを最新状態にするのはfetchで、作業ブランチとリモート追跡ブランチの両方を最新にするのがpull。

ふりかえってみると、①リモート追跡ブランチというものの存在をこれまで完全に無視していたこと、②fetchを理解せずにいきなりpullに慣れ親しんでしまったというのがfetchをちゃんと理解できてなかった原因だった気がします。

f:id:izumii-19:20190410134747p:plain

ああ、スッキリ。

2019/4/12追記 おまけ

f:id:izumii-19:20190410125212p:plain

originの存在についても曖昧な理解だったんですが、特にこれまで気にしなくても困らずにやってこれたのでスルーしてました。 結論からいうとリモートリポジトリにつける名前のことでした。

つまり、

https://github.com/izumii19/xxxxx.git = origin

だということです。

$ git push origin master

は、

https://github.com/izumii19/xxxxx.git”のmasterブランチに対してpushする

ということ。

ローカルでリポジトリを作成した場合はgit initしたあとに、そのリポジトリをリモートリポジトリに追加するためにgit remote add …をするのですが、そのときにリポジトリに名前をつけているはずです。*3

$ git remote add origin https://github.com/izumii19/xxxxx.git

originについてとてもわかりやすいサイトはこちら

reasonable-code.com

*1:ラッキングブランチという呼ばれ方もするらしい

*2:"origin"も厳密にいうと必ずしも"origin"じゃないかもしれないけど、今はそこは触れない

*3:ただ、いろんなサイトを見ていると「”git remote add origin リポジトリ名”と書けば良い」という説明もけっこうあるので、originをおまじないのように感じてしまうかもしれません。

Agile Japan 2018 札幌サテライトでモブプロを体験してきました

f:id:izumii-19:20190328171732p:plain:w400

2019年03月16日(土)にAgile Japanの札幌サテライトに参加してきました。

実はスタッフとして運営側で参加予定だったのですが、この数ヶ月前に次女が骨折してしまい手術やら通院やらで運営には全く関わることができず、さらに当日も通院日だったので結局サテライトには午後から参加しました。そのため午後から参加した内容のみ(=モブプロワーク)になります。

会場に到着してすぐ入り口から一番近いチームへ飛び入り参加したため、ワークの事前説明などはまったく聞かない状態で参加しました。多分、チームの皆さんに自己紹介もするの忘れてたと思います。

はじめてのGo言語

今日のお題は「自動販売機をプログラミングする」です。 言語の選択は自由ですがうちのチームは「誰もやったことがない言語でやりたい」という理由でGo言語にしました。 まずは「何を実装すれば自動販売機が完成するか」の設計から始めます。みんなでディスカッションして出てきたのは、こんなタスクでした。

  • 商品メニューを作成する
  • お金をいれる
  • 商品を選ぶ
  • 商品が出てくる
  • お釣りが出てくる(そのために、お釣りがいくらかを計算する)

これを今から実装していきます。 果たしてGo言語で自動販売機は完成するのでしょうか?

まず最初は「商品メニューを作成する」部分を実装します。具体的には商品リスト(1:水100円、2:コーラ120円、3:コーヒー130円…)を作成します。

「商品番号」「商品名」「値段」を持つ配列を作ればいいというところまではすぐにイメージが湧いたのですが、Go言語での書き方を誰も知りません。ということでナビゲーター全員でググりはじめ、ドライバーに指示を出し色々試してもらいます。

ここで(・∀・)イイ!と思ったのは、名付けなどの「動かすための実装」以外についてもリアルタイムで議論できること。 ひとりで実装していると自分だけの感覚で名前を付けてしまい後からわかりにくいと指摘を受けて修正することもあると思いますが、こういった点についてもその場でディスカッションしながら進めていけます。
「○○だからこういう名前のほうがいいんじゃない?」「ここで改行したほうが見やすくない?」などの会話も頻繁に交わしながら目的の実装も進めていけるので、出来上がったコードは自然と可読性の高いものになりますね。

f:id:izumii-19:20190328171215p:plain:w400

緊急タスク発生!

ここで緊急の割り込みタスク発生!なんとアイスの差し入れ(o'∀'人)
会場に冷蔵庫はないので、みんなプログラミングの手を止めて緊急アイスタイムに突入です*1
@nemorineはバナナを食べています。バナナは溶けないので急がなくても大丈夫なんですが、バナナを見ると脊髄反射的に「バナナ=俺が食わなきゃ」になってしまうようです。

f:id:izumii-19:20190328155342p:plain:w300

まさかの

その後も7分ずつナビゲーターとドライバーを交代し、チームで試行錯誤しながら自動販売機の実装を進めました。 本来であれば「お金をいれる」という機能では、

  • 硬貨の種類は、500円や100円などはOKだけど1円や5円はNG
  • 500円を入れる場合は、500円玉1枚、100円玉5枚など複数のパターンがありえる

などの考慮も必要なのですが、まずは「お金を入れる⇒商品を選ぶ⇒商品が出る」という一連の動作を完成させたかったので「500円を入れて水を買う」というフローの実現を目指しました。
「 商品メニューを作成する」「お金をいれる」というメソッドまでは全員で協力しながら実装することができたのですが、「商品を選ぶ」メソッドの作成で事件は起こりました。

まさかのどハマり。

「商品を選ぶ」というメソッドは、

  • 標準入力から商品番号を入力する("1"と入力)
  • 入力した商品番号と商品名を、標準出力に表示する("1:Water"と表示)

という感じで実現したかったのですが、水の商品番号である「1」を入れても画面に「1: Water」と表示されない! 「キーボードから入力した数値をキーにして商品リストの配列を検索し結果を表示する」だけの簡単なプログラム*2のはずなのにどうしても「1: Water」が表示されないんです。 ナビゲーターがググってはドライバーが試すをひたすら繰り返して30分ほど経過したところで、ついに原因を突き止めました。

原因は標準入力から商品番号を受け取った際に改行が入っていて、改行を含んだまま文字列から数値に変換しようとしてエラーになっていたのでした。

そう。ハマる時の原因はいつもこんな些細なこと。でも逆に些細すぎて1人だと見つけられなかったかもしれません。

ハマることさえ楽しい

この時思ったことが、モブプロだと「できない・わからない」ということにあまり罪悪感を感じないということでした。 例えば1人で実装していてハマってしまうと不安になったり焦りを感じてしまうのですが、モブプロの場合は「ここにいる全員がわからないんだから仕方ない」「チームでハマっている」という感覚なのです。
「こんな簡単なところで30分もハマってて誰もわからないなんて」という事実がなんだかおかしくなってきて、だんだんみんなハマりHighみたいになってました。

みんなでハマっていた分、画面に「1: Water」が表示されたときの喜びもひとしおで、みんなで声を出して「YATTA!!」と叫びました。プロのエンジニアがただ「1: Water」と表示することに30分もハマるなんてウケる!

あ、そうそう結論からいうと時間内に「お釣りを出す」の実装が間に合わず、500円を入れて100円の水しか買えないけどお釣りはでない自動販売機、つまり100円の水を500円で売るボッタクリ自動販売が完成してしまいました。

まとめ

モブプロの良さはなんでもチームで分け合えることだと思いました。

ハマった時わからないときも全員で解決に向けて取り組むので、個人で責任を負うという気持ちにはならず変な罪悪感はほとんど感じません。
逆に何かを達成できたときも「嬉しい」という感情をシェアすることで、何倍も嬉しく感じました。
コードを見ながら議論することでリアルタイムにリファクタリングできるので「レビュー⇒やり直し」というフローも必要ないし、ドライバーとしてタイピングしていない時間もコーディングに参加している感覚があり「チームみんなでコーディングしている」という気持ちになれます。

あんなにハマったのに振り返ってみると楽しい記憶ばかりでした。

プログラミングだけではなく、「モビング」という働き方をいろんなところで実践していけたらいいなぁと思いました。

講師の及部さん(@TAKAKING22)。3月の北海道でも元気に半袖です。

f:id:izumii-19:20190328171920p:plain

及部さんが書いた当日のブログはこちらです。 ワークショップで行った「Head Firstモブプログラミング」のスライドを見るとモブプロについて詳しく書かれていますのでぜひご覧ください。

takaking22.com

*1:アイスの画像がなくて残念

*2:実際には、商品リストの配列のIndexは0オリジンなので、標準出力に出力する際にはIndexに+1した値を商品番号としています。なので、標準入力から受け取った文字列を数値に変換し、1加算した値を標準出力に出力するということをやりました。