20200602のdockerに関する記事は13件です。

Dockerでコンテナ起動時に実行するコマンドを環境変数から渡す方法

個人的なメモ

検証環境でクライアントを見立てたホストを構築するのに使っている仕組みなので、セキュリティとかの考慮は一切ないです。
環境変数で設定の値だけじゃなくて、いっそのことコマンド自体を渡してしまおうという発想に至ってしまった自分を殺したい。

やり方

誰でも思いつく方法だと思うけど、単純に環境変数の中身をevalで実行するだけでいけた。

FROM centos:7.4.1708
ENV container docker

# required
# https://hub.docker.com/r/_/centos/
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]

RUN echo "eval \${STARTUP_RUN}" >> /etc/startup.sh
RUN echo "bash -c /etc/startup.sh" >> /etc/rc.local
RUN echo "/bin/bash">> /etc/rc.local
RUN chmod a+x /etc/rc.local
RUN chmod a+x /etc/startup.sh

CMD ["/bin/bash", "-c", "/etc/rc.local"]

環境変数で実行したいコマンドを渡してコンテナを動かす。

salacia@Vega:~/docker_env$ sudo docker run -it -d --name testhost --env STARTUP_RUN="echo 'hello' > /root/output" testimage
954f41cf05a374c00d74cd827bcd7409c150f60a1acd835824921523695404c5                                                                        

環境変数で指定したコマンドが実行されたことを確認する。

salacia@Vega:~$ sudo docker exec -it testhost cat /root/output
hello

結果

すごいことになる!

追記

今回rc.localやCMDに直接記述しなかったのは、rc.localに既にいくつかの処理を記述していて、rc.localに手を入れるのは最低限にしたかったためです。
シンプルにしたいならこんな感じで(動くことは確認してない)

FROM centos:7.4.1708

RUN echo "eval \${STARTUP_RUN}" >> /etc/startup.sh
RUN chmod a+x /etc/startup.sh
CMD ["/bin/bash", "-c", "/etc/startup.sh"]

docker-compose.ymlや、DockerfileのCMDに書いても動くと思います。(未検証)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

複数の docker-compose 間で共通の Network を使い通信できるようにする

目的

docker-compose で起動したコンテナは共通の Network 上にあるのでお互いに通信が可能だが、起動したいコンテナの数が増えてくると、1枚の docker-compose が肥大してしまう。
管理のために docker-compose を分けたいが、お互いに通信はできるようにしたい。
また、各コンテナには固定IPアドレスを付与したい。

共有する Docker ネットワークを作成する

ここでは shared-nw と名付けています。
固定IPアドレスを付与させるため、subnet も合わせて定義させています。
※docker-compose.yml のバージョンが3以上になると、gateway は定義できなかったように思います(未確認)。

$ docker network create shared-nw --subnet=172.30.0.0/16 --gateway=172.30.0.254
$ docker network ls
NETWORK ID          NAME            DRIVER              SCOPE
53bd0dc361fe        shared-nw       bridge              local

docker-compose.yml 内で共有ネットワークを使用するように宣言する

1つ目

  1. コンテナ(services:)を定義する箇所で networks > shared-nw > ipv4_address と固定IPアドレスを付与します。
  2. networks: を services: と同階層に定義し、使用するネットワーク(shared-nw) を宣言します。また、external: true とすることで、この docker-compose.yml 内ではなく、外部で定義されているネットワークを探すように指定します。
(省略)
services:
  {サービス名}:
    networks:
      shared-nw:
        ipv4_address: 172.30.0.2
(省略)
networks:
  shared-nw:
    external: true

2つ目

1つ目と同様に宣言していきます。
固定IPアドレスに1つ目とは違うアドレスを設定しています。

(省略)
services:
  {サービス名}:
    networks:
      shared-nw:
        ipv4_address: 172.30.1.2
(省略)
networks:
  shared-nw:
    external: true

両方の docker-compose を起動した上で通信確認してみます。
inet addr:172.30.1.2 のコンテナから、172.30.0.2 のコンテナに対して PING が通ることが確認できました。

$ docker exec spark-master101 ifconfig | grep "inet addr"
          inet addr:172.30.1.2  Bcast:172.30.255.255  Mask:255.255.0.0
          inet addr:127.0.0.1  Mask:255.0.0.0
$ docker exec spark-master101 ping 172.30.0.2
PING 172.30.0.2 (172.30.0.2): 56 data bytes
64 bytes from 172.30.0.2: seq=0 ttl=64 time=0.168 ms
64 bytes from 172.30.0.2: seq=1 ttl=64 time=0.111 ms
64 bytes from 172.30.0.2: seq=2 ttl=64 time=0.099 ms

結論

予め Docker network を作成しておく必要はありますが、docker-compose を分けて作成
しておけるメリットがあるので、ローカルで個人で管理する分には問題なさそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Win10でのDocker composeのあれこれ

WinのDockerコンテナ下でサーバのディレクトリとローカル(ホスト)側のディレクトリを同期したかったお話です。調べてもむずかしくてよくわかんなかったのでつくりました。
コマンド叩くのもいいけどいろいろ扱いやすくなるかなとʕ•̫͡ʕ•̫͡ʕ•̫͡ʕ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ•̫͡•ʔ

環境
- Windows 10 64bit
- Docker 2.3.0.3(Engine:19.03.8/Compose:1.25.5)
- MySQL 5.7
- WordPress 5.3.3

1.ローカルのディレクトリ構築

・ディレクトリを適当な場所に作る

$ mkdir hoge

・ディレクトリ配下でcmdを起動して「docker-compose.yml」を作成

docker-compose.yml
version: '3.3'

services:
   mysql:
     image: mysql:5.7
     restart: unless-stopped
     environment:
       MYSQL_ROOT_PASSWORD: root
       MYSQL_DATABASE: wp_db
       MYSQL_USER: wp_user
       MYSQL_PASSWORD: wordpress
   wordpress:
     depends_on:
       - mysql
     image: wordpress:latest
     ports:
       - "8080:80"
     restart: unless-stopped
     environment:
       WORDPRESS_DB_HOST: mysql:3306
       WORDPRESS_DB_NAME: wp_db
       WORDPRESS_DB_USER: wp_user
       WORDPRESS_DB_PASSWORD: wordpress
     volumes:
      - "./wp/:/var/www/html/"

豆知識
・インデントが揃っていないとコンテナ作成時にエラーが出るので気を付けましょう(1敗)
 タブインデントはなるべく使わないように
・.ymlの書き方はDockerのバージョンにより異なります

2.イメージ構築、コンテナ作成

・コンテナの起動

$ docker-compose up -d

イメージは勝手に作ってくれるのでこうなればOK

Starting docker-wp_mysql_1 ... done
Starting docker-wp_wordpress_1 ... done

・起動中のコンテナを確認

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
w0d5efbi4c28        wordpress:latest    "docker-entrypoint.s…"   10 minutes ago      Up 37 seconds       0.0.0.0:8080->80/tcp   docker-wp_wordpress_1
eab4edifn7f4        mysql:5.7           "docker-entrypoint.s…"   10 minutes ago      Up 37 seconds       3306/tcp, 33060/tcp    docker-wp_mysql_1

・DBを見る

$ docker exec -it docker-wp_mysql_1 bash
root@eab4edifn7f4:/# mysql -u wp_user -p
$ show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| wp-db              |
+--------------------+
2 rows in set (0.00 sec)

ちゃんと作成できてます。

3.起動

http://localhost:8080でブラウザを開く

screenshot.88.jpg

ローカルも.ymlのvolumeで指定したところにできてるか確認
screenshot.89.jpg

よくできました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

中学生がDockerについてイチから学んでみた(1)

まえがき

こんにちは!
二月からプログラミングを始めたとある中学生です。
今までCloud9でRailsを使っていたのですが、最近学校のプロジェクトに参加した際にDockerの存在を知りました。
Cloud9はrails sしてボタンを押すだけなので今まで環境構築に困ったことはなかったのですが、急にDockerに触れて何が何だか全く理解できませんでした。。
これから他の言語を使っていくにあたって、いつまでもCloud9に頼っていてはダメだと思ったので、イチからゆっくり学んでみたいと思います! 今回は導入編です。
間違えなどありましたらご指摘お願いします。

そもそもDockerって何? ざっくりと

docker.png
最初はガイドの冒頭部分を翻訳(自分で行っているので、間違っているかもです)して、簡単につかんでみようと思います。

Docker is a platform for developers and sysadmins to build, run, and share applications with containers. The use of containers to deploy applications is called containerization. Containers are not new, but their use for easily deploying applications is.
Containerization is increasingly popular because containers are:
Flexible: Even the most complex applications can be containerized.
Lightweight: Containers leverage and share the host kernel, making them much more efficient in terms of system resources than virtual machines.
Portable: You can build locally, deploy to the cloud, and run anywhere.
Loosely coupled: Containers are highly self sufficient and encapsulated, allowing you to replace or upgrade one without disrupting others.
Scalable: You can increase and automatically distribute container replicas across a datacenter.
Secure: Containers apply aggressive constraints and isolations to processes without any configuration required on the part of the user.
(Docker公式ガイドから抜粋)

Dockerは開発者・システム管理者たちのため、コンテナによってアプリが一通り走るようにしたり、アプリを共有できるプラットフォーム(基盤)です。コンテナを使ってアプリをデプロイすることは、*コンテナリゼーションと呼ばれます。コンテナは決して新しいものではないですが、簡単にアプリを開発、構築できます。
コンテナリゼーションがますます人気になっている理由は:
柔軟性:一番複雑なアプリでさえもコンテナリゼーションにできる(?)
軽量:コンテナを活用・ホストのkarnelを共有することでリソースを仮想マシンと比べて遥かに効率的にします。(?)
携帯性:自分のローカル環境で構築、クラウドにデプロイ、そしてどこでもアプリを走らせることができます。
緩やかな結びつき:コンテナはかなり十分です。コンテナは他のものを混乱させることなく、場所を変更したり更新することを許してくれます。(?)
拡張性:コンテナを増やし、複製をデータセンターに自動で分散させることができます。
安全:コンテナは、ユーザー側で構成を必要とせずに、積極的な制約と分離をプロセスに適用します。

?がついているところは翻訳が怪しいです。
よくわかんない単語が多いですね、、、
とにかくDockerは私たちが簡単に利用できる、軽量なアプリの実行環境を提供する便利なツールであり、しかも他の人が作った環境をクラウドから簡単に利用することができるという機能まで持ち合わせる素晴らしいアプリケーションということですね。

*コンテナリゼーション・・・定規格のコンテナに大小様々な貨物を積み込んで、コンテナごと一斉に運んでしまう輸送体系。つまり、色々な情報を一つのコンテナでまとめて運んじゃうこと。

イメージ・コンテナとは?

Dockerの記事とかをみても当然のようにイメージとかコンテナとか言っていますが、まず前提が分からない! ということありますよね、、
この2つはDockerを始めるにあたって重要概念です。
イメージ:軽量で単独で動くことができ、ソフトウェアを動かすための部品(設定ファイルなど)が全て詰め込まれたパッケージのこと。
コンテナ:イメージが実行されているときにあるもの。イメージからPCのメモリ内に展開し、実際に実行するもの。

コンテナはイメージの受け皿という認識です。
Dockerについてなるべくわかりやすく説明するによると

イメージは冷凍チャーハン、コンテナは皿に盛られたチャーハン

だそうです。冷凍チャーハン(イメージ)は温められ、皿に盛られてはじめて食べる(アプリを走らせる)という行為ができるようになるということですね。 間違っていたらごめんなさい。

Dockerのコンテナ型仮想化って?

Dockerはコンテナの仮想化ツールと言われます。正直、ド初心者の私にはそれだけ言われても分かりません、、ひとまず図で見てみます。
image.png

ホストOS上にコンテナによって区切った領域を作り出し、その中でプロセスと呼ばれる実行中のプログラムを動かします。
そしてコンテナはホストマシンを利用し、プロセスなどを隔離することで、あたかも別のマシンが動いているかのように振る舞ってくれます。

これらからまとめると、物理サーバー(実際に存在するサーバー)を必要とせずしない仮想環境で、コンテナという複数の独立した空間からアプリを走らせること、これがコンテナ型仮想化ということですね。

Dockerのいいとこ・悪いとこをざっくりと

VMと比べたりされますが、そのあたりはくわしくは説明しません。下のリンクの記事で詳しく書かれています。
VM・Dockerといった仮想化技術を理解する

いいとこ
・高速な起動
・メモリやディスクの消費が少ない
・ハードウェアに依存しない(これがDockerガイドのいう「Portable」ですね) => 汎用性
・他のユーザーが構築してくれた環境を簡単にコピーできる、環境構築が簡単になる。
・環境を作るのが失敗しても、ポイ捨てしてやり直せる。(これはありがたい!)

悪いとこ
・Windows Serverには対応しておらず、Docker Toolboxという別のソフトをインストールする必要がある
・コンテナでホストではない別のOSを動かすことはできない(windowsの上でLinuxを立ち上げる)

これ以外にもあるようですが難しいものも多かったのでここまでにしときます

ざっとみていいとこが多いですね! 
Macユーザーにとっては本当に使いやすいアプリです。

参考文献・画像

仮想化の新潮流「コンテナ」とは
Dockerのメリット・デメリットまとめ

おわりに

ここまで読んでくださった方ありがとうございました
今回は短くなってしまいましたが、次からは実際にアプリを入れて操作していきます。
かなり習得するのには時間がかかりそうですが、インフラ周りのことを知ることはとても大事だと思うのでDockerと仲良くしていきたいですね!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コントロールプレーンの具体的な動作について調べてみた

Kubernetesを学習するにあたり、コントロールプレーンの具体的な動作が分からなかったので調べてみました。(CoreDNSは後日投稿します、あと誤字脱字がひどいと思うので時間がある時修正します。。)
特にkube-apiserverの認証/認可/Admission Controllerのあたりが分からない方は参考になるかと思います。

言葉の定義

  • マスターノード
    クラスタ全体がマニフェスト等で指定されたdesired stateになり続けるようにワーカーノードのKubernetesオブジェクトに対して管理(Kubernetesオブジェクトの作成や他のコンポーネントに対するタスクの割り振りなど)を行う。
    また、その重要性から大規模なプロジェクトやミッションクリティカルなプロジェクトなどでは可溶性と冗長性が考慮され、複製することもできる。
  • ワーカーノード
    マスターノードからのタスクを受け実行する。自ノードの状態を監視し、マスターノードに通知する。
  • Kubernetesオブジェクト
    ストレージやネットワークなど一般的なリソースも含めて抽象的な構成ファイルとして表したもの(マニフェストと呼ばれyamlファイルが一般的)、もしくはKubernetes APIにより作成された実態

Kubernetesコントロールプレーンとは

Kubernetesはマスターノードとワーカーノードで構成されており、デフォルトで稼働しているk8sプロセスは以下となる。

ノード プロセス
マスターノード kube-apiserver
マスターノード kube-scheduler
マスターノード kube-controller-manager
マスターノード etcd
ワーカーノード kubelet
ワーカーノード kube-proxy
ワーカーノード(拡張コンポーネント) CoreDNS

また、kube-apiserver、kube-controller-manager、kube-schedulerはコントロールプレーンと呼ばれており、kubernetesクラスタ内の一つのマスターノードで実行される。

Kubernetesコントロールプレーンの動作

kube-apiserver

各k8sオブジェクトからRESTfulなリクエストを受け取り、k8sオブジェクトを管理する処理をするように指示する。
また、kube-apiserverはetcdに格納されているオブジェクト情報(定義されたあるべき姿)を更新する役割を持っている。
そのため、kube-apiserverはetcdを保護するためのフィルタとしての役割を持ち、アクセス権限があるユーザやService Accountを使用する必要がある。また、大量のリクエストにも対応できるように、水平スケールすることができる。
上記を踏まえてkube-apiserverを利用する際は以下の機能が使用される。
1. 認証(Authentication)
2. 認可(Authorization)
3. リクエストの更新、制御(Admission Controller)
以下は上記機能に関して説明する。

認証(Authentication)

接続を試みた際、接続元を確認しkube-apiserverへのアクセス権を持っていれば認証する。接続元は ユーザーアカウントService Account のどちらかである。

  • ユーザアカウント

    一般的なユーザと同じ扱いでパブリッククラウドのユーザ(AWSで言う所のIAMユーザ)でKubernetesの管理外クラスタ外からPod内のプロセスを操作する。全てのnamespace間で一意でなくてはならない

  • Service Account

    Pod内のプロセスやアプリケーション自体が持つ権限付きの認証アカウントで事前に発行する必要がある。
    kube-apiserverにアクセスする際、ユーザー単位ではなく、Pod内のプロセスやアプリケーション単位でアクセスできるようにすることで細かい権限制御が可能になる。
    また、認証にはデフォルトで作成されたSecret(Service Accountに属するk8sオブジェクト)に付与されているAccess Tokenが用いられ、SecretごとPodにマウントされる。(自前で作成したSecretはPodにマウントして使用できるが、指定しない場合はdefaultという名前のSecretが自動的にマウントされる。)
    また、defaultという名前のService Accountは、namespaceを作成した時にService Account Controllerで作成され、Account TokenはToken Controllerによって発行される。
    Service Accountはnamespaceごとに一意であれば良い。

認可(Authorization)

認証アカウント(ユーザーアカウントやService Account)、Pod内のプロセス、所属してるグループによってk8sオブジェクトに対してどのような操作を許可/拒否するかを評価、制御する。
評価方法として認可モジュールを使用するが、ここには何種類かあり、推奨されているものがRBACである。
RBACは役割ベースのアクセス制御機能であり、権限が定義されたRoleと認証アカウントをRole Bindingにより関連づけてアクセスを制御する。
以上の仕組みからRBACは「誰がどのk8sオブジェクトに対してどのような操作(CRUD操作)を許可/拒否する」といったアクセス制御を設定できる。
また、RoleとRole Bindingには対象範囲(クラスタ全体かnamespaceか)があり、適切に組み合わせる必要がある

リクエストの更新、制御(Admission Controller)

一度kube-apiserverにより認証/認可されたk8sオブジェクトを変更するためのリクエストを制御する機能。
k8sオブジェクトを変更する際、リクエストによりMutating Controller(Mutating Admission Webhook)とValidating Controller(Validating Mutating Webhook)が起動する。
Mutating Controllerはk8sオブジェクトの変更を実行し、Validating Controllerは変更後のk8sオブジェクトが変更リクエスト通りになっていることを確認する。

kube-scheduler

Podが作成された時に適切なノードを割り振る。
割り振るノードの決定要素としては、ノードのリソース要件、様々なポリシーによる制約、Affinity/UAnti-Affinityの設定などが挙げられる。
ノードを決定しPodを配置するまでの具体的な順を以下に示す。

  1. Deployment ControllerやReplicaset ControllerなどによってPodが作成される
  2. kube-schedulerがPodが作成されたことを検知し、起動するノードを選択、kube-apiserverに対して割り当てるように依頼 ノードの選択に関してはPredicate、Priority、ハイスコアノードの選択の順で行う。
    参考
  3. Podの定義を変更(spec.Nodenameの変更)し、ノードを割り当てられたPodを再度検知
    1. Pod作成依頼をkubeletにしてノードに作成される。
    2. kube-apiserverにPodのステータスを更新するように依頼
    3. Podのステータスが更新されることを確認

kube-controller-manager

コントローラの上位プロセスで以下のコントローラが一つのプロセスとしてコンパイル、実行される。

  • ノードコントローラ
    ノードがダウンした際の通知、対応を担当
  • レプリケーションコントローラ
    レプリケーションオブジェクトで指定されたPod数を維持する
  • エンドポイントコントローラ
    ServiceとPodを紐づけてエンドポイントを払い出す
  • サービスアカウントコントローラ/トークンコントローラ
    作成したnamespaceに対してアカウント(Service Account)とAPIアクセストークンを作成する

etcd

etcdはk8sオブジェクト情報を格納する分散型のkvsで最重要なk8sオブジェクトである。
etcdの特徴はスプリットブレインを許容せず、以下の特徴がある。

  • RAFTを使用した障害回復 etcdクラスタにあるリーダノードが故障した時に、周囲のフォロワノードの一つがリーダに立候補し、周囲のフォロワノードの過半数の投票が得られた時、そのノードはリーダノードとなる。
  • 高速な書き込み
  • REST APIを使用したデータの入出力
  • SSLクライアント証明書認証 また、etcdはkubernetesでも最重要なk8sオブジェクトであるため、大規模システムではマスターノードとは別に構築する必要があり、etcdクラスタはフォールトトレランスを考慮して最低5ノード (2ノード故障しても稼働できるように)している。

kubelet

kube-apiserverから指定されたコンテナを見つけコンテナランタイムによってPod内で起動したり、Podやワークノード上で展開されてるインフラリソースのライフサイクルを管理して障害発生後再起動した後、成功/失敗に関わらずkube-apiserverに報告する役割を持つ。
つまり、各コンテナがPodで実行されてることを保証する役割を持つ。
また、kubeletは運用の拡張性などの観点からPodをSandboxにする必要があり、コンテナランライムやネットワークプラグイン、ストレージプラグインを自由に決めることができるため、それぞれインターフェース(CRI、CNI、CSI)を経由する。
特にCRIを経由する際、Image ServiceRuntime Serviceを取り扱い、コンテナの起動やライフサイクルの管理を行なっている。
以下それぞれ説明する。

  • Image Service
    コンテナレジストリから指定されたコンテナを取得、削除するサービス
  • Runtime Service コンテナのライフサイクルを管理したり、Pod経由でコンテナに直接アクセスできるサービス

また、kubeletはetcdにあるコンテナ情報ではなく、OCIにより変換されたコンテナ情報をコンテナランタイムに渡す。
Podのライフ管理はliveness ProveReadness Proveの設定をPodにすることで可能。

kube-proxy

Service(内部ロードバランサー)の名前とエンドポイントをiptablesに対応づけるプロセス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker registoryアクセス時にhttp: server gave HTTP response to HTTPS clientエラーが出た場合の対策方法

docker registoryアクセス時にエラー

Error response from daemon: Get http myreg.example.com:5000 http: server gave HTTP response to HTTPS client

Dockerデーモンの設定が足りていないので、
dockerの--insecure-registryに追記して設定を変更

/etc/systemd/system/docker.service.d/docker.conf
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// --insecure-registry=myreg.example.com:5000

その後、Dockerデーモンを再起動して解決

sudo systemctl daemon-reload
sudo systemctl restart docker 

参考

systemd と Docker の管理・設定
[SOLVED] ERROR: Error response from daemon: Get https://myregistry:5000: http: server gave HTTP response to HTTPS client
Dockerの設定ファイルはどこ!!
最近のUbuntu(15.04以降)でDockerの--insecure-registryの設定
「server gave HTTP response to HTTPS client」と言われてDocker Private registoryのpushやpullができなかったときの対処
プライベートDocker-Registryにhttpで接続 [Docker-ce Linux]

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6のシステムテストがDockerコンテナ上で実行できない。

Railsでアプリ作ったので、Dockerコンテナ上でシステムテストを実行してみよう。

以前書いた記事の続きで、Dockerの勉強がてら、デスクトップの無いコンテナ上でシステムテストなんてできるのか、試してみたところ、ハマりにハマったのでやっぱり記事に残しておこうと思います。

参考にしたもの。

CapybaraのReadMe
ヘッドレス Chrome ことはじめ

環境

主なコンポーネントのバージョンは以下の通りになります。
詳しくは後ろの方にDockerファイルを掲載させていただきます。
Google Chrome 83.0.4103.61
Rails 6.0.3
Ruby 2.6.5

事象

システムテストを実行してみると以下のようなエラーが発生します。
色々書いてますが、"Chrome has crashed."とあるので、chromeが起動しないのでしょう。

Selenium::WebDriver::Error::UnknownError: unknown error: Chrome failed to start: exited abnormally.
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

切り分け

本当にchromeが起動しないのか、コマンドラインで試してみました。

shell
# ヘッドレスモードでamazon.comにいってみます。
$ google-chrome --headless https://www.amazon.com/ --dump-dom > hoge.txt

# =>こんなメッセージが出てきてしまい、動きません。 
# Running as root without --no-sandbox is not supported. See https://crbug.com/638180.

# では、--no-sandboxをつけて試してみます。
$ google-chrome --headless --no-sandbox https://www.amazon.com/ --dump-dom > hoge.txt

# => hoge.txtの中身は誌面の都合上割愛させていただきますが、
#    ちゃんとamazonのトップページと思しきレスポンスが書き込まれます。

解決方法

切り分けた結果から、chrome起動時のオプションが変更できれば解決できると思い、色々調べた結果、railsのtest/application_system_test_case.rbを以下の通り書き換えることで解決できました。

test/application_system_test_case.rb
require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  # 元々書かれていた以下のコードは破棄
  # driven_by :selenium, using: :chrome, screen_size: [1400, 1400]

  # ここから追加 ====>
  # ドライバを新しい名前で追加します。
  Capybara.register_driver :selenium_chrome_headless_nosandbox do | app |
    # Chrome用のオプションを設定
    options = Selenium::WebDriver::Chrome::Options.new;
    options.add_argument('--headless');
    options.add_argument('--no-sandbox');

    # 当初、以下のオプションを付けないと動かないと勘違いしていたのですが、不要なようです。
    # options.add_argument('--disable-gpu');

    # 作成したオプションを指定してchrome用のドライバを生成します。
    driver = Capybara::Selenium::Driver.new(app, browser: :chrome, options: options);

  end

  # 作ったドライバをdriven_byで指定してあげます。
  driven_by :selenium_chrome_headless_nosandbox

  # <=== ここまで追加

end

おまけの使用環境

構築に使用したDockerファイル

一応、環境構築に使ったDockerファイルも公開させていただきます。

Dockerfile
# ruby 2.6.5のベースイメージを利用しました。
FROM ruby:2.6.5

# nodejsのLTS版を自動でインストールしてみたくてnvmを入れておきました。
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

# nodejsのLTS版をインストール(他に良い書き方ないだろうか。。)
RUN ["/bin/bash", "--login", "-c", "nvm install --lts"]

# aptのダウンロード先リポジトリにgoogleを追加するため、keyを追加
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -

# aptのダウンロード先リポジトリにdl.google.com/linux/chrome/debを追加
RUN echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list

# apt-getでchrome等をインストール
RUN apt-get update -qq && apt-get install -y npm google-chrome-stable

# yarnをインストール
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
RUN ["/bin/bash", "--login", "-c", "yarn install --check-files"]

# bundlerとrailsのgemをインストール
RUN gem install bundler
RUN gem install rails

コンテナ起動方法

上記DockerファイルにはENTRYPOINTやCMDを指定してないので、そのままでは起動できません。
/bin/bashを引数に入れて起動してください。
起動例を以下に記載しておきます。

shell
# 適当なディレクトリに、上のDockerfileをおきます。
# 配置イメージはこのような感じです。
$ ls -l .
total 8
-rw-r--r--  1 dareka  staff  1049  6  2 14:20 Dockerfile

# Dockerイメージをビルドします。
$ docker build --tag testimage .

# イメージが作れたのでコンテナ起動
$ docker container run -it --name rortest testimage /bin/bash
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsアプリを作成してGitHubにSSHでPush

VPSのセットアップしてcapistranoでデプロイする流れで、Railsアプリを作成する必要があったので簡単にまとめます。情報量の関係上、Rails5です。安全に行きたいので。

環境

Rails 5.2.2
Ruby 2.4.1
MySQL 5.7

You're on Railsを表示

$ mkdir sample_app
$ cd sample_app
$ touch Dockerfile docker-compose.yml Gemfile Gemfile.lock
Dockerfile
FROM ruby:2.4.1

RUN apt-get update -qq && \
  apt-get install -y build-essential \ 
  libpq-dev \        
  nodejs           

RUN mkdir /app_name 
ENV APP_ROOT /app_name 
WORKDIR $APP_ROOT

COPY ./Gemfile $APP_ROOT/Gemfile
COPY ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN bundle install
COPY . $APP_ROOT
docker-compose.yml
version: "3"
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"
  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    links:
      - db

Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.2'
Gemfile.lock
#空
$ docker-compose run web rails new . --force --database=mysql --skip-bundle
$ docker-compose build --no-cache #--no-cacheオプションが無いと、bundle installが実行されないことがある
config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db

development:
  <<: *default
  database: app_name_development

test:
  <<: *default
  database: app_name_test

production:
  <<: *default
  database: app_name_production
  username: app_name
  password: <%= ENV['APP_NAME_DATABASE_PASSWORD'] %>
$ docker-compose up
$ docker-compose run web rails db:create

http://localhost:3000 にアクセスしてYay!You're on Rails!を確認

適当なページを作成

$ docker-compose run web rails g controller tests index
config/routes.rb
Rails.application.routes.draw do
  get 'tests/index'
  root to: 'tests#index'
end

http://localhost:3000 にアクセスして表示を確認

sshキーペアを作成しGitHubに登録

すでに登録済みの場合はとばしてください。

$ mkdir -p ~/.ssh/github
$ cd ~/.ssh/github
$ ssh-keygen -f id_rsa
$ vim ~/.ssh/config
~/.ssh/config
Host github.com #ここが「github」だと動かないので注意
  HostName github.com
  Port 22
  IdentityFile ~/.ssh/github/id_rsa
  User git
$ pbcopy < id_rsa.pub #公開鍵をクリップボードにコピー

その後以下の手順でGitHubに登録

  • GitHubにログイン
  • 右上のアイコン > Settings > SSH and GPG keys に移動
  • New SSH keyをクリック
  • クリップボードにコピーした公開鍵をペーストして保存

GitHubにリポジトリを作成

  • GitHubにログイン
  • 画面右上のアイコン > Your repositoriesをクリック
  • Newをクリック
  • リポジトリ名を入力し Create repository をクリック

Push

$ git add -A
$ git commit -m "First commit"
$ git remote add origin git@github.com:<githubのアカウント名>/<リポジトリ名>.git
$ git push -u origin master
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker 主に使うコマンド(備忘)

主に使うDockerコマンド

・docker デーモンの実行(再起動などでデーモンが起動していないとき)
$ sudo systemctl start docker

・Dockerfileをビルド
$ docker build -t イメージ名:タグ名 Dockerfileのディレクトリ

・イメージからコンテナを起動
$ docker run --name コンテナ名 イメージ名:タグ /bin/bash
    -i :ホスト側の入力をコンテナの標準出力とつなげる
    -t :Dockerコンテナ内の標準出力とホスト側の出力とつなげる
    -p xxxx:yyyy :ホストのportxxxxをDockerコンテナのportyyyyに転送する
    -d :バックグラウンドで実行
ex) docker run -it -p 10000:8888 --name tmp tmp:latest /bin/bash

・docker imageの確認
$ docker images

・実行中のコンテナの確認
$ docker ps
    -a :停止中のDockerコンテナも含めて表示

・コンテナに入る(対話コマンドを実行)
$ docker exec -it コンテナ名orコンテナID /bin/bash

・停止しているコンテナを起動
$ docker start コンテナ名orコンテナID

・起動しているコンテナに入る
$ docker attach コンテナ名orコンテナID

・コンテナを削除(複数指定可能)
$ docker rm コンテナ名orコンテナID (コンテナ名orコンテナID・・・)

・イメージを削除(複数指定可能)
$ docker rmi イメージ名orイメージID (イメージ名orイメージID・・・)

・コンテナをコミット
docker commit コンテナ名orコンテナID イメージ名:タグ名

・イメージを保存する
docker save イメージ名 > 任意.tar

・保存したイメージをロードする
docker load < 任意.tar
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6】Docker+Rails6+puma+nginx 【環境構築*初心者必見】

本記事の目的

本記事ではDockeを用いてRails6の環境構築を行うことを目的としています。
Rails6ではyarnというjsのパッケージ管理ツールとwebpackerがデフォルトとなっているので、Rails5の手順で環境構築を行うとエラーが出てしまいます。
よって本記事ではRails6対応の環境構築を目的としています。

※Dockerそのものについてはあまり触れませんので、Docker基礎を学習してからの方が良いかもしれません。

ディレクトリ構成

環境構築する際の全体の構成を以下に示します。
ここでは「webapp」というファイルを作成してアプリケーションを作っていきます。

全体構成
/webapp
├── containers
│   └── nginx
│       ├── Dockerfile
│       └── nginx.conf
├── docker-compose.yml
├── Dockerfile
├── environments
│   └── db.env
├── Gemfile
└── Gemfile.lock

Dockerfile(Rails用)

Rails用のDockerfileは以下のように記述します。
Rubyのバージョンは2.7.1を用います。

ここでのポイントは、yarnとNode.jsのインストールコマンドを書いている点です。

また、本記事ではNodeのバージョンを現時点での最新14.0を使っています。
もし、アプリケーションを作成した時に「Nodeをアップグレードしてください」と出た場合、setup_14〜の数字を最新のバージョンに変えてみてください。

Dockerfile
FROM ruby:2.7.1

# リポジトリを更新し依存モジュールをインストール
RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       nodejs

# yarnパッケージ管理ツールインストール
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn

# Node.jsをインストール
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    apt-get install nodejs

# ルート直下にwebappという名前で作業ディレクトリを作成(コンテナ内のアプリケーションディレクトリ)
RUN mkdir /webapp
WORKDIR /webapp

# ホストのGemfileとGemfile.lockをコンテナにコピー
ADD Gemfile /webapp/Gemfile
ADD Gemfile.lock /webapp/Gemfile.lock

# bundle installの実行
RUN bundle install

# ホストのアプリケーションディレクトリ内をすべてコンテナにコピー
ADD . /webapp

# puma.sockを配置するディレクトリを作成
RUN mkdir -p tmp/sockets

Gemfile

インストールするRailsのバージョンを指定します。
Rails6に対応するように書いています。

Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6'

Gemfile.lock

こちらはファイルの作成のみでOKで、中身は書かなくて構いません。

Dockerfile(Nginx)

Dockerfile
FROM nginx:1.15.8

# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*

# Nginxの設定ファイルをコンテナにコピー
ADD nginx.conf /etc/nginx/conf.d/webapp.conf

# ビルド完了後にNginxを起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

Nginx設定ファイル

nginx.conf
# プロキシ先の指定
# Nginxが受け取ったリクエストをバックエンドのpumaに送信
upstream webapp {
  # ソケット通信したいのでpuma.sockを指定
  server unix:///webapp/tmp/sockets/puma.sock;
}

server {
  listen 80;
  # ドメインもしくはIPを指定
  server_name example.com [or 192.168.xx.xx [or localhost]];

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  # ドキュメントルートの指定
  root /webapp/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @webapp;
  keepalive_timeout 5;

  # リバースプロキシ関連の設定
  location @webapp {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://webapp;
  }
}

DB情報ファイル

ここでのユーザー名やパスワードは変更して構いません。

db.env
MYSQL_ROOT_PASSWORD=db_root_password
MYSQL_USER=user_name
MYSQL_PASSWORD=user_password

docker-compose.yml

docker-vcompose.yml
version: '3'
services:
  app:
    build:
      context: .
    env_file:
      - ./environments/db.env
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/webapp
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
      - log-data:/webapp/log
    depends_on:
      - db
  db:
    image: mysql:5.7
    env_file:
      - ./environments/db.env
    volumes:
      - db-data:/var/lib/mysql
  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
    ports:
      - 80:80
    depends_on:
      - app
volumes:
  public-data:
  tmp-data:
  log-data:
  db-data:

Railsの生成(Rails new)

Dockerコンテナ内でRailsを生成しなければいけないので、docker-compose run コマンドを使います。
ここではGemをインストールしません。

$ docker-compose run --rm app rails new . --force --database=mysql --skip-bundle

puma.rbの編集

先ほどのコマンドで生成されたpuma.rbファイルを以下のように編集します。

puma.rb
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

app_root = File.expand_path("../..", __FILE__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true

database.ymlの編集

Railsはデフォルトで、localhost上でDBが動作するようになっているので、hostを先ほど作成したdbに変更します。
また、ここにおける「MYSQL_USER」 と「 MYSQL_PASSWORD」 は DBファイルで定義した環境変数名を設定してくだい。

database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch('MYSQL_USER') { 'root' } %>
  password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %>
  host: db

development:
  <<: *default
  database: webapp_development

test:
  <<: *default
  database: webapp_test

イメージのビルド

docker-compose.ymlで、app・db・webのbuildに指定されているDockerfileを元にイメージを作成します。

$ docker-compose build

コンテナ起動

ビルドが完了しイメージができたら以下のコマンドでコンテナを立ち上げます

$ docker-compose up -d

ここでコンテナが起動しているのかを以下のコマンドを入力して確認します。

docker-compose ps

そうすると以下のようにコンテナの状況が見れると思います。

    Name                  Command               State          Ports       
---------------------------------------------------------------------------
webapp_app_1   bundle exec puma -C config ...   Up                         
webapp_db_1    docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp
webapp_web_1   /bin/sh -c /usr/sbin/nginx ...   Up      0.0.0.0:80->80/tcp 

webpackerのインストール

起動したコンテナ内でwebpackerをインストールするので、以下のコマンドでインストールします。
Dockerfileになにかしら記入すれば、いちいちコマンドを入力しなくても良いとは思いますが、今回はこの方法を用います。

docker-compose exec app rails webpacker:install

以下のメッセージが出現すればインストール完了です。

Webpacker successfully installed ? ?

DBの作成

DBの作成は必須なので、コンテナ内でDBを作成します。

docker-compose exec app rails db:create

確認

以下のリンクをクリックして「You're on Rails」が表示されるか確認しましょう。
http://localhost
上手くいけば、Rails6で起動できていることが分かるかと思います。

スクリーンショット 2020-06-02 14.03.37.png

補足

localhostに変更内容が反映されていなくて、思うような結果が得られなければ、一度コンテナを閉じて、再起動させるのがいいでしょう。

コンテナ終了
docker-compose down
コンテナ起動
docker-compose up 

参考サイト

以下の記事を参考にしながら環境構築をしました。
本記事だけでなく、以下のサイトも確認してみてください。

①Docker + Rails + Puma + Nginx + MySQL
②DockerでRuby on Railsの環境構築を行うためのステップ【Rails 6対応】
③[Docker] Node.js以外のコンテナに追加でNode.jsの最新版をインストールするDockerfileの記述

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6】Docker+Rails6+puma+nginx+mysql【環境構築*初心者必見】

本記事の目的

本記事ではDockeを用いてRails6の環境構築を行うことを目的としています。
Rails6ではyarnというjsのパッケージ管理ツールとwebpackerがデフォルトとなっているので、Rails5の手順で環境構築を行うとエラーが出てしまいます。
よって本記事ではRails6対応の環境構築を目的としています。

※Dockerそのものについてはあまり触れませんので、Docker基礎を学習してからの方が良いかもしれません。

ディレクトリ構成

環境構築する際の全体の構成を以下に示します。
ここでは「webapp」というファイルを作成してアプリケーションを作っていきます。

全体構成
/webapp
├── containers
│   └── nginx
│       ├── Dockerfile
│       └── nginx.conf
├── docker-compose.yml
├── Dockerfile
├── environments
│   └── db.env
├── Gemfile
└── Gemfile.lock

Dockerfile(Rails用)

Rails用のDockerfileは以下のように記述します。
Rubyのバージョンは2.7.1を用います。

ここでのポイントは、yarnとNode.jsのインストールコマンドを書いている点です。

また、本記事ではNodeのバージョンを現時点での最新14.0を使っています。
もし、アプリケーションを作成した時に「Nodeをアップグレードしてください」と出た場合、setup_14〜の数字を最新のバージョンに変えてみてください。

Dockerfile
FROM ruby:2.7.1

# リポジトリを更新し依存モジュールをインストール
RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       nodejs

# yarnパッケージ管理ツールインストール
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn

# Node.jsをインストール
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    apt-get install nodejs

# ルート直下にwebappという名前で作業ディレクトリを作成(コンテナ内のアプリケーションディレクトリ)
RUN mkdir /webapp
WORKDIR /webapp

# ホストのGemfileとGemfile.lockをコンテナにコピー
ADD Gemfile /webapp/Gemfile
ADD Gemfile.lock /webapp/Gemfile.lock

# bundle installの実行
RUN bundle install

# ホストのアプリケーションディレクトリ内をすべてコンテナにコピー
ADD . /webapp

# puma.sockを配置するディレクトリを作成
RUN mkdir -p tmp/sockets

Gemfile

インストールするRailsのバージョンを指定します。
Rails6に対応するように書いています。

Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6'

Gemfile.lock

こちらはファイルの作成のみでOKで、中身は書かなくて構いません。

Dockerfile(Nginx)

Dockerfile
FROM nginx:1.15.8

# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*

# Nginxの設定ファイルをコンテナにコピー
ADD nginx.conf /etc/nginx/conf.d/webapp.conf

# ビルド完了後にNginxを起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

Nginx設定ファイル

nginx.conf
# プロキシ先の指定
# Nginxが受け取ったリクエストをバックエンドのpumaに送信
upstream webapp {
  # ソケット通信したいのでpuma.sockを指定
  server unix:///webapp/tmp/sockets/puma.sock;
}

server {
  listen 80;
  # ドメインもしくはIPを指定
  server_name example.com [or 192.168.xx.xx [or localhost]];

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  # ドキュメントルートの指定
  root /webapp/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @webapp;
  keepalive_timeout 5;

  # リバースプロキシ関連の設定
  location @webapp {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://webapp;
  }
}

DB情報ファイル

ここでのユーザー名やパスワードは変更して構いません。

db.env
MYSQL_ROOT_PASSWORD=db_root_password
MYSQL_USER=user_name
MYSQL_PASSWORD=user_password

docker-compose.yml

docker-vcompose.yml
version: '3'
services:
  app:
    build:
      context: .
    env_file:
      - ./environments/db.env
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/webapp
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
      - log-data:/webapp/log
    depends_on:
      - db
  db:
    image: mysql:5.7
    env_file:
      - ./environments/db.env
    volumes:
      - db-data:/var/lib/mysql
  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
    ports:
      - 80:80
    depends_on:
      - app
volumes:
  public-data:
  tmp-data:
  log-data:
  db-data:

Railsの生成(Rails new)

Dockerコンテナ内でRailsを生成しなければいけないので、docker-compose run コマンドを使います。
ここではGemをインストールしません。

$ docker-compose run --rm app rails new . --force --database=mysql --skip-bundle

puma.rbの編集

先ほどのコマンドで生成されたpuma.rbファイルを以下のように編集します。

puma.rb
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

app_root = File.expand_path("../..", __FILE__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true

database.ymlの編集

Railsはデフォルトで、localhost上でDBが動作するようになっているので、hostを先ほど作成したdbに変更します。
また、ここにおける「MYSQL_USER」 と「 MYSQL_PASSWORD」 は DBファイルで定義した環境変数名を設定してくだい。

database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch('MYSQL_USER') { 'root' } %>
  password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %>
  host: db

development:
  <<: *default
  database: webapp_development

test:
  <<: *default
  database: webapp_test

イメージのビルド

docker-compose.ymlで、app・db・webのbuildに指定されているDockerfileを元にイメージを作成します。

$ docker-compose build

コンテナ起動

ビルドが完了しイメージができたら以下のコマンドでコンテナを立ち上げます

$ docker-compose up -d

ここでコンテナが起動しているのかを以下のコマンドを入力して確認します。

docker-compose ps

そうすると以下のようにコンテナの状況が見れると思います。

    Name                  Command               State          Ports       
---------------------------------------------------------------------------
webapp_app_1   bundle exec puma -C config ...   Up                         
webapp_db_1    docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp
webapp_web_1   /bin/sh -c /usr/sbin/nginx ...   Up      0.0.0.0:80->80/tcp 

webpackerのインストール

起動したコンテナ内でwebpackerをインストールするので、以下のコマンドでインストールします。
Dockerfileになにかしら記入すれば、いちいちコマンドを入力しなくても良いとは思いますが、今回はこの方法を用います。

docker-compose exec app rails webpacker:install

以下のメッセージが出現すればインストール完了です。

Webpacker successfully installed ? ?

DBの作成

DBの作成は必須なので、コンテナ内でDBを作成します。

docker-compose exec app rails db:create

確認

以下のリンクをクリックして「You're on Rails」が表示されるか確認しましょう。
http://localhost
上手くいけば、Rails6で起動できていることが分かるかと思います。

スクリーンショット 2020-06-02 14.03.37.png

補足

localhostに変更内容が反映されていなくて、思うような結果が得られなければ、一度コンテナを閉じて、再起動させるのがいいでしょう。

コンテナ終了
docker-compose down
コンテナ起動
docker-compose up 

参考サイト

以下の記事を参考にしながら環境構築をしました。
本記事だけでなく、以下のサイトも確認してみてください。

①Docker + Rails + Puma + Nginx + MySQL
②DockerでRuby on Railsの環境構築を行うためのステップ【Rails 6対応】
③[Docker] Node.js以外のコンテナに追加でNode.jsの最新版をインストールするDockerfileの記述

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose down

docker-composeで作られたコンテナやネットワークのを一括で削除するコマンドです。

docker-compose down

デフォルトではコンテナとネットワークのみを削除しますが、オプションを付ければイメージやボリュームも削除できます。

イメージの削除

docker-compose down --rmi 'type'

typeには任意の値を指定します。
指定できるのは、alllocalです。

  • all

サービスで使われている全てのイメージを削除します。

  • local

イメージフィールドにカスタムタグのないイメージだけ削除します。

ボリュームの削除

docker-compose down -v, --volumes

composeファイルのvolumesセクションのボリュームを削除します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker上のphpコンテナでcomposer installしたら、メモリ不足で落ちた話

はじめに

docker上でlaravelの開発していて、必要なライブラリをcomposerでインストールしようとしたら下記のエラーが出て詰まった、、、:sweat_smile:

エラーメッセージ

Using version ^4.3 for laravel/socialite
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)

Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/bin/composer.phar/src/Composer/DependencyResolver/Solver.php on line 223

原因調査

コンテナに入って、以下のコマンドを実行

$ php -r 'phpinfo();' | grep memory_limit

$ memory_limit => 128M => 128M

確かにデフォルトのphpのメモリが少ない、、、

ちなみに -r は <?php を略したもので、
コマンドライン上でphpのプログラムを実行するためのオプションです!

↓参照元 phpコマンドのオプション
https://www.php.net/manual/ja/features.commandline.options.php

対処方法

  • phpのコンテナのdockerファイルに以下を追加
php/Dockerfile
 COPY php.ini /usr/local/etc/php/ 
  • php.iniをdockerファイルのディレクトリに作成
php/php.ini
  memory_limit = -1

 -1は上限なしという意味

  • コンテナを再起動し中に入ってメモリを確認する
  $ php -r 'phpinfo();' | grep memory_limit           
  $ memory_limit => -1 => -1

 php.iniの設定に切り替わってる〜!
 ナイスですね〜〜〜:thumbsup:と全裸の監督から聞こえてきそうです!

結果

もう一度composer installしたら、、、

Package manifest generated successfully

無事インストールできました!マーベラス!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む