質問: 閲覧ありがとうございます! 『コンテナは、イメージから作成されたものであり、作業履歴を保存するもの』っと書かれていたので、作業履歴**すべて**(手で打ったコード等)を保存するものだと思っていました。 しかし実際、コンテナは**コンテナを動かしたコマンド(作業履歴)を保存するもの**であると`docker ps -a`で分かったのですが、以下の疑問が出ました。 ### 環境 docker for Mac docker version: 17.03.1-ce Users/****/workspace下で、Quickstart: Compose and Railsリンク内容を構築 ``` ###Dockerfile FROM ruby:2.3.3 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock RUN bundle install ADD . /myapp ###docker-compose.yml version: '2' services: db: image: postgres web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp ports: - "3000:3000" depends_on: - db ``` ### 疑問1:コンテナの中身の違い ``` $ docker-compose run web rails g contoller StaticPages home $ docker inspect [generate contoller container ID] "Cmd": [ "rails", "destroy", "controller", "StaticPages", "home" ] $ docker-compose run web rails g destroy StaticPages home $ docker inspect [destroy controller container ID] "Cmd": [ "rails", "destroy", "controller", "StaticPages", "home" ] ``` 上記のコマンドより、各コンテナは、個々が独立しており、かつ、他のコンテナのコマンドを有していないと考えたのですが(destroyコンテナはgenerate controllerコマンドを有してない) なぜ`docker-compose run web ****`で動くのですか? `generate controller`や`destroy controller`をするには、まず`rails new`でアプリケーションを作成する必要があると思いますが、`rails new`コンテナは別にあります。 仮に、generateやdestroyをしたい場合には、`rails new`コンテナ(コマンド)を継承しなければ出来ないと思うのですが、『各コンテナは、個々が独立しており、かつ、他のコンテナのコマンドを有していない』と考えているため、`rails new`無しで`generate & destroy`が出来てしまうというおかしな考えになってしまいました。 私の考えがおかしいのは、間違いないのですが、どこが間違っているのかを調べても見つからないため、困っています。 ### 疑問2:localhost:3000で制作仮定がブラウザで見れる理由 rails tutorialを勉強している間、何も考えずに`docker-compose up`と`localhost:3000`をして、勉強過程をブラウザ確認していました。 勉強過程がブラウザで確認できたのは、volumeでホスト側のファイルをゲスト側にマウントしているからであり、実際に自分が打ったコードはコンテナ(ゲスト側)が有しているわけではない。っという事ですか? 説明が下手な、長い質問文になってしまいましたが、よろしくお願いいたします!
回答: まず少しDockerfileについて少し。 DockefileはFROMで指定されているイメージに対してシェル的に変更をして新しくイメージを作り出すものです。なのでこのDockerfileをcomposeで指定している時点で/myappが同梱された状態のイメージが生成されるはずです。しかしcomposeではそこにさらにvolumeを指定しています。 なので本来同梱したはずの/myappが同期フォルダによって上書きされています。 なのでどちらかを指定すれば良いと思います。 > > 疑問1:なぜdocker-compose run web で動くのか > > > まず、`dokcer-compose run`コマンドは、docker-composeの特定のコンテナを起動させるものです。 なのでdockerのなかにdbとwebがありますが、その中でwebコンテナが生成されて立ち上げられます。またdepends(依存関係)にdbを指定しているのでdbも立ち上げられます。 本来はdocker-compose upコマンドでdockerを実行すべきですが、今回に限ってうまく動いています。 でもなるべく`docker-compose run`ではなく`docker-compose up`を使うべきだと思います。 さらに、`docker-compose run`は、runのあとにcomposeに書いた名前だけではなくさらに何かを書いた場合そのコマンドが実行されるので、myappに対して動作を行っているのだと思われます。 > > 疑問2:localhost:3000で制作仮定がブラウザで見れる理由 > > > docker-compose.ymlでportを指定した場合、ホストのポートとコンテナのポートをつなげることができます。つまり、今回の場合はホストの3000版に来た通信はすべてwebコンテナの3000版へ転送されることになります。なのでローカルで起動しているrailsではなくコンテナの中で実行されているrailsへ正常にアクセスしているものだと思います。