mind.

学んだことの記録

Railsチュートリアルで作成したサンプルアプリをDockerで動かす手順

雑に備忘録

基本的な内容は下記ページに書かれているもので、それをRailsチュートリアルで作成したサンプルアプリ向けにまとめました。
docs.docker.com ローカルPCで動かす想定です。

以下、コマンドとファイルの記載内容

nano Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /sample-app
WORKDIR /sample-app
COPY Gemfile /sample-app/Gemfile
COPY Gemfile.lock /sample-app/Gemfile.lock
RUN bundle install
COPY . /sample-app

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

※Dockerサイトのテンプレートから「Myapp」を「sample-app」に置き換えています。

nano Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'
touch Gemfile.lock
nano entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
nano docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/sample-app
    ports:
      - "3000:3000"
    depends_on:
      - db

※Dockerサイトのテンプレートから「Myapp」を「sample-app」に置き換えています。

リポジトリのクローン

git clone [リポジトリのURL]

リポジトリのファイルを移動

cd sample_app
mv * ../
mv .git ../
mv .gitignore ../
cd ..
rm -rf sample_app

イメージ作成

docker-compose build

データベース作成

docker-compose run web rake db:create

データベースのマイグレーション

docker-compose run web rake db:migrate

サンプルデータの反映

docker-compose run web rake db:seed

アプリケーションのコンテナ起動

docker-compose up

完了

余談

Postgresqlのコンテナ起動してもRails側でDBの設定変えないとデフォルトのSQLite使っちゃいます。
Dockerfile、docker-compose.yml、entrypoint.sh、Gemfile.lockはリポジトリに入れておくと便利です。

AWSでEC2インスタンスを最小構成で作成する手順

最小構成でWebサーバー用のEC2インスタンスを立ち上げる手順をメモしておきます。
後述する書籍の内容を参考に、チェックシート的な使い方ができるようにしました。

目標

VPC、サブネット、EC2インスタンスそれぞれ一つずつ作成し、EC2インスタンスSSHでログインする。

手順

  1. VPCを作成する
    「名前タグ」は自由、「IPv4 CIDR ブロック」は「10.0.0.0/16」
  2. サブネットを作成する
    「名前タグ」は自由、「VPC」は1で作成したもの、「アベイラビリティーゾーン」は自由、「IPv4 CIDR ブロック」は「10.0.1.0/24」
  3. インターネットゲートウェイを作成する
    「名前タグ」は自由
  4. インターネットゲートウェイVPCにアタッチする
    3で作成したインターネットゲートウェイを選択した状態で、「アクション」→「VPCにアタッチ」→「使用可能な VPC」に1で作成したVPCを選択して「インターネットゲートウェイのアタッチ」
  5. ルートテーブルを作成
    「名前タグ」は自由、「VPC」は1で作成したもの
  6. ルートテーブルにサブネットを関連付ける
    5で作成したルートテーブルを選択して、画面中央部にある「サブネットの関連付け」タブを選択した状態で「サブネットの関連付けの編集」
    2で作成したサブネットがリストに表示されていることを確認して選択し「保存」
  7. ルートテーブルにインターネットゲートウェイのルートを追加する
    5で作成したルートテーブルを選択して、画面中央部にある「ルート」タブを選択した状態で「ルートの編集」
    送信先」は「0.0.0.0/0」、ターゲットは3で作成したインターネットゲートウェイを選択
  8. EC2インスタンスの作成
    「ネットワーク」は1で作成したVPC、「サブネット」は2で作成したもの、「自動割り当てパブリック IP」は「サブネット設定を使用(有効)」を選択
    「ネットワークインターフェース」の「プライマリIP」に「10.0.1.10」を入力
    「セキュリティグループの設定」で「新しいセキュリティグループを作成する」を選択、「SSH」(初期状態で設定済み)と「HTTP」のようなWebアプリへアクセスするためのルールを設定
    他の項目は自由
    秘密鍵を忘れずにダウンロードする
  9. ローカルPCからSSHログインできるか確認する
ssh -i [秘密鍵のパス] ec2-user@[EC2インスタンスのIPアドレス]

参考書籍

丁寧な説明で分かりやすくおすすめです。

余談

「6.ルートテーブルにサブネットを関連付ける」を忘れがち

GitLabをhttpsでアクセスするように設定した後はGitLab APIのオプションにverifyを追加する

仕事で使っているGitLabをhttpsに設定したときにバックアップに使っているスクリプトを変更し忘れたので自戒を込めて書きます。

Pythonで確認

元にしたコードは下記の以前書いた記事に記載しています。
learning-mind.hatenablog.com

def get_all_user_email_dict():
    headers = {
        'Private-Token': os.environ['ACCESS_TOKEN'],
    }
    params = (
        ('page', '1'),
        ('per_page', '1000'),
    )

    response = requests.get('https://XXXXX/api/v4/users', headers=headers, params=params, verify="ca.crt")
    data = response.json()
    path_dict = dict()
    for row in data:
        username = json.dumps(row["username"], indent=4).replace("\"", "")
        path_dict[username] = json.dumps(row["email"], indent=4).replace("\"", "")

    return path_dict

下記の部分を修正しました。

    response = requests.get('https://XXXXX/api/v4/users', headers=headers, params=params, verify="ca.crt")

verify="ca.crt""ca.crt"はクライアント証明書のファイル名です。
verifyのパラメータはFalseでも処理は進みますが、警告が表示されます。

コマンドで確認

元にしたコマンドは↓ learning-mind.hatenablog.com

curl --cacert ca.crt --header "Private-Token: $ACCESS_TOKEN" https://XXXXX/api/v4/users | jq .projects[].path

URLおよびファイル名は環境に合わせてください。
--cacert ca.crtが追加されています。
--cacertcurlのオプションで、ca.crtはクライアント証明書のファイル名です。

感想

自分が書いた記事に助けられることは多い

『アマゾンのすごいルール』を読んで

どのような本か

アマゾンで敷かれているルールについて、著者である佐藤将之さんがアマゾン社員時代に経験したこと踏まえて説明されている本です。
内容は、2018年に出版されたということもあり、紹介されているルールはネットニュースでの話題になったことも多く、目新しいことは多くはありませんでした。 ただ、著者の経験したことは読んでいて状況がイメージしやすく、アマゾンのルールの本質を理解できました。

印象に残った箇所

AWSのサービス開始に至った経緯

アメリカの人たちはクリスマスに集中してものを買うそうです。
クリスマス商戦の商品を補充しておくための大規模な倉庫を保有しているのですが、クリスマス以外の時期は他の業者に貸しています。
それと同様の発想で、クリスマス時期の大量アクセスに耐えきる程のサーバーを閑散期に貸し出すAWSが生まれたそうです。
AWSを知ったときは「先見の明があるなあ」くらいにしか思っていませんでしたが、倉庫の例を知ることで、AWSは生まれるべくして生まれたと思えました。

「在庫なし」の商品ページへのアクセス数をチェックしている

アマゾンはロングテール戦略をとっていて、めったに売れない商品、所謂「死に筋商品」も商品が無くならない限り商品ページを載せ続けます。
その戦略をとるに至ったのは、「在庫なし」の商品ページへのアクセス数をチェックしていたからということでした。
欲しい商品の在庫が無い状態が続いているなら何回もアクセスしてみるといいかもしれませんね。(笑)

移動サーバールーム

ある時、大企業のデータをAWSに移行するとき、遅い転送速度をフォローするために、トラックに積んだサーバーに太い光ファイバーを使ってデータを移して運んだそうです。
これはアマゾンがスピードを重視しているという方針から行ったそうです。
ドラマ『シリコンバレー』でも、経緯は全く違いますがサーバーをトラックで運ぶというエピソードがありましたね。
もしかしたらアマゾンのエピソードが元ネタになっているのかも知れません。

全体的に、読んでいると著者のアマゾンに対する強い愛が伝わってくる文章でした。

PCの再起動時にplymouthが止まってGitLabが起動しなかった件

困った……

仕事で使っているGitLabのサーバーPCを再起動した後、いつも通りブラウザでページを開こうとするとエラー画面が表示されました。
サーバーにSSHで入って状態を見ると、GitLabとそれに関わるプロセスが起動していませんでした。
設定は、システム起動時に自動的に起動するようにしていたにも関わらず起動できないとはむむむ……。

とりあえずGitLabの起動コマンドを打ってみたものの失敗しました。

gitlab-ctl start

下記記事と現象は同じでした。
writesnow.net

$ sudo gitlab-ctl start
fail: alertmanager: runsv not running
fail: gitaly: runsv not running
fail: gitlab-monitor: runsv not running
fail: gitlab-workhorse: runsv not running
fail: logrotate: runsv not running
fail: nginx: runsv not running
fail: node-exporter: runsv not running
fail: postgres-exporter: runsv not running
fail: postgresql: runsv not running
fail: prometheus: runsv not running
fail: redis: runsv not running
fail: redis-exporter: runsv not running
fail: registry: runsv not running
fail: sidekiq: runsv not running
fail: unicorn: runsv not running

上記ページには解決策も書かれていますが、僕の環境では下記コマンドを実行しても反応が無いという状況でした。

systemctl start gitlab-runsvdir

その他、Rubyのバージョンを確認したりもしましたが、僕が使っていたGitLabはOmnibus packageでインストールしたので関係ありませんでした。

結論

plymouth-quit-waitが動き続けていたため他のプロセスが起動できなかったことが原因でした。
(GitLab依存の問題ではありませんでしたので、影響は他のアプリにもあったかもしれません)

原因の特定に至った過程

この現象についてGitLabの公式ページに書かれていました。

docs.gitlab.com

Since GitLab 11.2, the gitlab-runsvdir starts during the multi-user.target instead of basic.target. If you are having trouble starting this service after upgrading GitLab, you may need to check that your system has properly booted all the required services for multi-user.target via the command:

つまり、誰かがGitLabに必要なサービスの起動を妨げているようです。
公式ページに従って、妨げているサービスを確認します。

systemctl -t target

このとき、loaded inactive deadとなっているサービスが二つありました。
(抜粋)

graphical.target       loaded inactive dead   start Graphical Interface
multi-user.target      loaded inactive dead   start Multi-User System

この二つが原因のようです。
前述の公式ページに書かれている通り、次のコマンドでsystemdのキューを確認します。

systemctl list-jobs

結果(抜粋)

plymouth-quit-wait.service           start running

plymouth-quit-waitrunningのまま止まっていました。

plymouthとは

plymouthはシステム起動時および終了時のスプラッシュを表示するソフトだそうです。

access.redhat.com

調べると、下記ページのようにアンインストールすることで解決できると書かれていました。

www.hiroom2.com

しかし、業務で使用しているということもあり極力既存のモジュールをアンインストールしたくはありませんでした。

解決策

GUIモードで起動しようとして止まっているので、CUIモードに切り替えると解決しました。

systemctl isolate multi-user.target

access.redhat.com

念のためキューを確認します。

# systemctl list-jobs
No jobs running.

# systemctl -t targetを実行するとrunningのままのサービスはありませんでした。

感想

正直危なかった……。先輩に教えてもらえなかったら解決できてなかったかもしれません。感謝です。
そろそろLPICとか取った方がいいのかとも思いました。

『NETFLIXの最強人事戦略~自由と責任の文化を築く~』を読んで

どのような本か三行で

  • 全員が事業に関する問題についても知る権利がある
  • そこで働いていたことを誇れるような会社にしよう
  • 「10試合」ごとに人事考課を行う

感想

一見大胆に見える人事戦略ですが、エピソードを交えながら説明されているのでとても説得力があり参考になりました。
かなり厳しい言葉で従来の評価制度や採用フローを否定しています。(ビアサーバーがあったり専属シェフを否定していたのは意外でした)
人事に関わるテクニックを学ぶという目的だけでなく、Netflixの物語としてもとても面白く読める本でした。

全員が事業に関する問題についても知る権利がある

この本で一貫して伝えられていることは、情報を隠さず社員全員に伝えることがハイパフォーマンスを保つために必要だということです。
情報とは、事業に関わることだけでなく、人事考課に関わることも含まれます。
給与の格差が発生することを認めつつ、給与を決める基準を明確に説明できるようにしておくことで従業員が不満を抱くことを防ぐ効果があるということです。
(やはり真壁司令は正しかったということか)

また、適切な採用には、人事担当者にも事業に関する知識を持たせることが必要と書かれています。
これは僕も常々考えていたことでしたが、人事担当者にどこまで理解してもらうかが難しいですよね。
ただ、採用担当者に少しでも事業の知識があれば、現場に投入されてからのスキルの不一致はへると思います。

そこで働いていたことを誇れるような会社にしよう

アメリカは日本よりも解雇の規制が緩いので、手続き上は簡単に解雇できます。
しかし、解雇するときはアメリカの人事も苦悩するようで、解雇の際、円満に退社させるためにはどうすればいいかが書かれています。
「あなたのスキルが今の会社に合わなくなった」という論旨で正直に話し合えば従業員は納得して次の会社に移ることができるということです。

「10試合」ごとに人事考課を行う

この「10試合」というのはあるホッケーチームで行っている面談の頻度です。
僕が今いる会社でもそうですが、大抵の企業は一年あるいは半年に一回人事考査を行います。
これでは、指摘されてから評価が確定するまでに改善の時間が無く、従業員にとっては理不尽なやり方だということです。
Netflixではより面談の頻度を増やしてフィードバックの機会を従業員に与えているので、従業員が行動を改める機会を持たせているということでした。

まとめ

人事に関わる人には管理職、一般職問わずおすすめします。
社員の採用だけでなく、現場のマネージャーにもおすすめできる一冊です。
この本にも書かれている通り、いきなりすべての施策を実践することは無理でも、特定の部署だけから始めるなど、できるところから試していきたいと思います。

NETFLIXの最強人事戦略~自由と責任の文化を築く~
Amazon CAPTCHA

セルフホストしたGitLabにhttpsでアクセスできるようにする。ドメイン名を使用せず、警告を出さずに――

環境

  • vagrantで起動したCentos7.6
  • GitLab12.10をインストール済み
  • サーバーのIPアドレスは「192.168.33.10」

手順

下準備

  • sudoを打たなくていいようにする
sudo su -
cd /etc/ssl
mkdir myCA
cd myCA
mkdir newcerts
mkdir certs
mkdir crl
mkdir private
chmod 700 private

証明書作成

openssl genrsa 2048 > server.key
  • 証明書署名要求を作成する
openssl req -new -key server.key > server.csr

対話モードで入力するパラメータは適宜入力する。
Common Nameは必須で適当に入力すること。
他は空でOK。

openssl x509 -days 36500 -req -signkey server.key < server.csr > server.crt

36500は有効期限を示す。

  • opensslの設定ファイル変更
nano /etc/pki/tls/openssl.cnf

変更点のみ記載

[ CA_default ]
dir = /etc/ssl/myCA
certificate = $dir/ca.crt
private_key = $dir/ca.key

[ usr_cert ]
subjectAltName = @alt_names

[ req ]
req_extensions = v3_req

[ v3_req ]
subjectAltName = @alt_names #追記

[ alt_names ]
DNS.1 = localhost
IP.1 = 192.168.33.10
IP.2 = 127.0.0.1
  • オレオレ証明局の秘密鍵と証明書ファイルを作成
openssl req -new -x509 -sha256 -days 36500 -newkey rsa:4096 -out ca.crt -keyout private/ca.key

秘密鍵パスフレーズ解除

openssl rsa -in private/ca.key -out private/ca.key
openssl req -new -sha256 -days 36500 -newkey rsa:4096 -out server.csr -keyout private/server.key

秘密鍵パスフレーズ解除

openssl rsa -in private/server.key -out private/server.key
openssl x509 -req -in server.csr -CA ca.crt -CAkey private/ca.key -CAcreateserial -out server.crt -days 36500 -sha256 -extensions SAN -extfile <(printf "
[SAN]
subjectAltName=@alt_names
basicConstraints=CA:FALSE
[alt_names]
DNS.1=localhost
IP.1=192.168.33.10
IP.2=127.0.0.1")
cp -i private/server.key /etc/pki/tls/private/
cp -i server.crt /etc/pki/tls/certs/
chmod 400 /etc/pki/tls/private/server.key
chmod 400 /etc/pki/tls/certs/server.crt
  • ca.crt をrsyncなりsambaなりでクライアントPCに保存する

  • クライアントPCのブラウザでca.crt をインポートする

GitLab設定

  • GitLabの設定ファイル変更
nano /etc/gitlab/gitlab.rb
external_url 'http://localhost'
 ↓
external_url 'https://192.168.33.10'

# nginx['ssl_certificate'] = "/etc/gitlab/ssl/#{node['fqdn']}.crt"
# nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/#{node['fqdn']}.key"
 ↓
nginx['ssl_certificate'] = "/etc/pki/tls/certs/server.crt"
nginx['ssl_certificate_key'] = "/etc/pki/tls/private/server.key"
  • 設定ファイルの変更を適用
gitlab-ctl reconfigure
  • ブラウザで動作確認

https://192.168.33.10

参考URL

www.gitlab.jp

qiita.com

qiita.com

LANのIPアドレスに対してSANを適用して真正なSSL証明書を作成する手順 · GitHub

tech.sanwasystem.com