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?

Dockerを触ってみる

Last updated at Posted at 2025-04-13

Dockerを触ってみようと思う

自分はほとんど触ったことない。友人が使ってるのを隣で指くわえてみてました。

しかしある程度どんなものかは知っているので早速触ってみる

Dockerfileってなんだ

DockerfileはImageの設計図だ。
Imageはコンテナの設計図だ
つまり

Dockerfile

Image

コンテナ

って感じで作られるぽい。

じゃあDockerfileから直接コンテナつくれよって思った。
Dockerfile

コンテナ

Imageがなぜ生成されるのかというと、
Imageを作成する際に前回のImageを作った際の結果をキャッシュして保存しておいて、
二回目以降のImage作成を高速にしてくれる。

あとはDocker hubにあげて共有できる

React + Laravel + Nginx

この構成でDockerの環境を構築する

image.png

コンテナのどう分けるのか、ホストOSにフレームワークは入れて開発するのかとか、
わからないことだらけでしたが、とりあえずこの画像みたいに組んでいきたいです。

LaravelはAPIを返すだけに注力してもらいます。

フォルダ構成
|---backend
|  |---laravel
|  |---Dockerfile-dev
|  |---Dockerfile-prod
|
|---web
|  |---react
|  |---Dockerfile-dev
|  |---Dockerfile-prod
|  |---nginx.conf
|
|---docker-compose-dev.yml
|---docker-compose-prod.yml

ymlファイルとDockerfileは開発環境用と本番環境用を作りました。
これが一般的なんでしょうか???わかりません

追記 2025/04/16
開発環境と本番環境でDockerfileを変えることは無いそうです。

Dockerfile

web
FROM node:20-alpine AS build
COPY ./react-introduce/package.json ./react-introduce/yarn.lock /app/
WORKDIR /app
RUN yarn install
COPY ./react-introduce/ /app/
RUN yarn build

FROM nginx:alpine
WORKDIR /usr/share/nginx/html
COPY --from=build /app/build /usr/share/nginx/html
COPY ./react-introduce/.env /app/.env
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx","-g", "daemon off;"]

この書き方はマルチステージビルドを用いています。

web
FROM node:20-alpine AS build
...
RUN yarn build

ここで1つのコンテナでビルドとインストールを行います。

web
FROM nginx:alpine
...
COPY --from=build /app/build /usr/share/nginx/html

ココから別のコンテナで前のコンテナはすでに止まっています
前のコンテナからビルドしたフォルダだけをコピーしているので効率的で、軽い

web
CMD ["nginx","-g", "daemon off;"]

これはNginxをフォアグラウンドで起動するためのコマンドです。
バックグランドで起動するプロセスだとコンテナは止まってしまいます。

web
CMD ["nginx"]

これだとバックグランドで起動するのでダメです。

CMDRUNの違い
Imageからコンテナが作られたときに動くのRUN
コンテナが起動して最初に動くのがCMD

CMDはコンテナの核となるプロセスを動かすために使うような感じかなと思います。

Dockerfile内ではCMDは一回しか使えません

backend
FROM node:20-alpine AS install
WORKDIR /laravel
COPY ./laravel-introduce/package.json /laravel/
RUN npm install

FROM php:8.2-fpm

RUN apt-get update \
    && apt-get install -y zlib1g-dev mariadb-client vim libzip-dev \
    && docker-php-ext-install zip pdo_mysql

WORKDIR /laravel
COPY ./laravel-introduce/ /laravel
COPY ./laravel-introduce/.env /laravel/.env
COPY --from=install /laravel /laravel
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
RUN composer install
CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8000"]

ymlファイル

ymlファイルは複数のコンテナを管理するためのファイル

docker-compose-prod
services:
  backend:
    build:
      context: ./backend
      dockerfile: ./Dockerfile-prod
    ports:
      - "8000:8000"
    networks:
      - app-network

  web:
    build:
      context: ./web
      dockerfile: Dockerfile-prod
    ports:
      - "80:80"
      - "5173:5173"
    environment:
      - HOST=0.0.0.0
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

backendwebはコンテナの名前でありコンテナ間でアクセスするためのホスト名になる

docker-compose-dev
volumes:
      - ./backend/laravel-introduce:/laravel
....

volumes:
      - ./web/react-introduce/:/app

開発用ではそれぞれのフレームワークのプロジェクトファイルを丸ごとマウントしています。

マウントするとホストOSのファイルを変更した場合、コンテナ内のファイルもリアルタイムで変わります。

嵌ったところ

ボリュームマウントでdockerfileCOPYした内容が消えてる問題

Dockerfile-dev
FROM node:20-alpine AS build
COPY ./react-introduce/package.json ./react-introduce/yarn.lock /app/
WORKDIR /app
RUN yarn install
COPY ./react-introduce/ /app/
RUN yarn build

FROM nginx:alpine
WORKDIR /usr/share/nginx/html
COPY --from=build /app/ /app/
COPY ./react-introduce/.env /app/.env
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 5173
CMD ["yarn", "dev"]

こんな感じで開発用のDockerfileでもyarn installしてそのディレクトリを
COPY --from=build /app/ /app/で持ってきてる。

volumes:
      - ./web/react-introduce/:/app

それでボリュームをマウントしている。

何がしたかったか

ホストOSでは依存関係をインストールしていません。つまりnode_modulesなどの
yarn installして作成されるディレクトリはホストOSにはありません

すべてコンテナ内で完結したかったのでホストOSにあるソースコードをマウントして
ホストOSにあるソースコード + コンテナでインストールした依存関係
こんな感じしたかったのです。
ですがマウントする際に、既にあるファイルは隠されるそうです。
image.png

volumes:
      - ./web/react-introduce/:/app

これはホストosのreact-introduceディレクトリappディレクトリにマウントします。
そしてマウントされる順序はdockerfileのCOPYよりも後です。

ホストOSの依存関係がない状態のディレクトリで上書きしているので、
ホストOSにあるソースコード + コンテナでインストールした依存関係

ホストOSにあるソースコードコンテナでインストールした依存関係を上書きしていたんですね

これに気づかずにかなり時間を使ってしまいました。
ホストOSにあるソースコード + コンテナでインストールした依存関係
これの実現方法はわかりません。有識者の方教えてください。

疑問

CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8000"]

本番用のDockerfileでもartisan serveしています。ここに違和感を感じます。
artisan serveというのは本番で使うものでないと思っています。

COPY --from=build /app/build /usr/share/nginx/html

ですがnginxのドキュメントルートにはReactのビルドしたフォルダを置いています。
ドキュメントルートにLaravelpublicディレクトリを置いてもいいものか
ドキュメントルートを共有していいのかわからずにしぶしぶartisan serveするという選択をしました。

後から聞いたのですがDockerfileは本番も開発も一緒なのが一般的だそうです。

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?