【Docker】DooD(Docker outside of Docker) 構成でDockerコンテナ内で docker-compose を利用する

こんにちは

昨日に引き続き DooD(Docker outside of Docker) 関連の記事になります

今回は DooD(Docker outside of Docker) で Dockerコンテナ内で docker-compose を利用できるようにしてみたので、ここに残しておきます

なお、DooD(Docker outside of Docker)  については、前回の記事で割としっかりめに記載しているので、この記事では説明しません

 

■概要

APPコンテナからWebコンテナへ対して docker compose コマンドを利用したコンテナ操作を実現してみます

なお、docker-compose.yml の構成や基本的なDockerファイルの中身は 前回の記事 と変わりません

そのうえで、前回とは異なり docker-compose.yml をホストOSとAPPコンテナ間でバインドマウントし、コンテナ内でも docker-compose.yml を認識できるようにします

 

■流れ

流れとしては、まず docker-compose.yml をホストOSとAPPコンテナ間でバインドマウントしない場合は、どうなるのか確認します

その後、docker-compose.yml をバインドマウントして、正常に実行できることを最後に確認します

 

1. docker-compose.yml をバインドマウントせずに、APPコンテナからWebコンテナへ操作

2. docker-compose.yml をバインドマウント

3. docker-compose.yml をバインドマウントした状態で、APPコンテナからWebコンテナへ操作

 

■手順

1. docker-compose.yml をバインドマウントせずに、APPコンテナからWebコンテナへ操作

まずは、ホストOS上の docker-compose.yml の中身を確認し、バインドマウントしていないことを確認します

version: "3.9"
services:
  web01:
    build:
      context: ./
      dockerfile: web/Dockerfile
    container_name: web01-container
    volumes:
      - ./app/src:/var/www/vhosts/www.example.com/public_html
    depends_on:
      - app01
    ports:
      - "80:80"

  app01:
    build:
      context: ./
      dockerfile: app/Dockerfile
    container_name: app01-container
    volumes:
      - ./app/src:/var/www/vhosts/www.example.com/public_html
      - /var/run/docker.sock:/var/run/docker.sock
    restart: always
    ports:
      - "9000:9000"

 

次に、APPコンテナ へ入ります

docker container ps -a
CONTAINER ID   IMAGE                        COMMAND                  CREATED        STATUS          PORTS                                         NAMES
7405f96f6c4d   nginx_php-fpm_docker-web01   "/docker-entrypoint.…"   22 hours ago   Up 29 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp           web01-container
f491c7cd0510   nginx_php-fpm_docker-app01   "docker-php-entrypoi…"   22 hours ago   Up 19 minutes   0.0.0.0:9000->9000/tcp, [::]:9000->9000/tcp   app01-container

 

docker exec -it f491c7cd0510 bash

 

docker composeコマンドが入っていることを確認し、Webコンテナへ対して docker compose コマンドを実行します

www-data@f491c7cd0510:~/vhosts/www.example.com/public_html$ docker compose version
Docker Compose version v2.27.1

→ APPコンテナ内であれば、docker compose コマンドが通ることを確認

 

docker compose exec web01 nginx -v
www-data@f491c7cd0510:~/vhosts/www.example.com/public_html$ docker compose exec web01 nginx -v
no configuration file provided: not found

→ docker-compose.yml がないので、configuration file のエラーが出ました

 

2. docker-compose.yml をバインドマウント

それでは、docker-compose.yml をバインドマウントするので、まずは APPコンテナ内で docker-compose.ymlを配置する用のディレクトリを作成します

なお、docker-compose.yml のみ /home/docker ディレクトリ直下へ配置した理由としては、WebとAPPコンテナでドキュメントルート配下を共有しており、

もしドキュメントルート直下に配置すると、最悪インターネット上から確認可能になる可能性があるためです

FROM php:8.0.30-fpm

#php.ini用confファイルコピー
COPY ./app/conf/disable_display_error.ini /usr/local/etc/php/conf.d/

#php-fpm用confファイルコピー
COPY ./app/conf/zz-docker.conf /usr/local/etc/php-fpm.d/

#ドキュメントルート作成
RUN apt-get update -y && \
    apt-get install -y vim less && \
    docker-php-ext-install pdo_mysql && \
    mkdir -p /var/www/vhosts/www.example.com/public_html && \
    mkdir -p /home/docker ★

COPY ./app/src /var/www/vhosts/www.example.com/public_html

# Docker CLI(静的バイナリ)
RUN curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.0.3.tgz \
    | tar xz --strip-components=1 -C /usr/local/bin docker/docker

# Docker Compose v2 プラグイン
RUN mkdir -p /usr/local/lib/docker/cli-plugins && \
    curl -fsSL "https://github.com/docker/compose/releases/download/v2.27.1/docker-compose-linux-x86_64" \
    -o /usr/local/lib/docker/cli-plugins/docker-compose && \
    chmod +x /usr/local/lib/docker/cli-plugins/docker-compose

RUN groupmod -g 1000 www-data
RUN usermod -u 1000 www-data

RUN groupadd -g 991 docker && usermod -aG docker www-data

# ユーザー切り替え
USER www-data

#作業ディレクトリ設定
WORKDIR /var/www/vhosts/www.example.com/public_html

#ポート開放
EXPOSE 9000

→ ★の個所を追記しました

 

次に docker-compose.yml でバインドマウントします

version: "3.9"
services:
  web01:
    build:
      context: ./
      dockerfile: web/Dockerfile
    container_name: web01-container
    volumes:
      - ./app/src:/var/www/vhosts/www.example.com/public_html
    depends_on:
      - app01
    ports:
      - "80:80"

  app01:
    build:
      context: ./
      dockerfile: app/Dockerfile
    container_name: app01-container
    volumes:
      - ./app/src:/var/www/vhosts/www.example.com/public_html
      - /var/run/docker.sock:/var/run/docker.sock
      - ./docker-compose.yml:/home/docker/docker-compose.yml ★
    restart: always
    ports:
      - "9000:9000"

→ カレントディレクトリ直下の docker-compose.yml をコンテナ内のパスにバインドマウントしています

 

3. docker-compose.yml をバインドマウントした状態で、APPコンテナからWebコンテナへ操作

それでは、設定反映のため docker-compose を利用してコンテナ削除と起動を実施します

docker-compose down && docker-compose up -d
docker container ps -a

 

最後に、APPコンテナへ入り、Webコンテナへ操作してみます

docker exec -it f45dbc30d49a bash

 

/home/dockerまで移動し、docker compose コマンドを実行します

docker compose exec web01 nginx -v
WARN[0000] /home/docker/docker-compose.yml: `version` is obsolete
service "web01" is not running

→ service “web01” is not running のエラーになりました

 

■なぜエラーになった?

それでは、なぜ カレントディレクトリ直下に docker-compose.yml が存在するにもかかわらず、エラーになったのでしょうか?

原因としては、docker-compose のプロジェクトが関係してきます(参考:単一ホスト上で、複数の環境を分離)

まず docker-compose におけるプロジェクトとは、1つの設定ファイル(compose.yaml)で管理される複数のコンテナやネットワークなどの集まりを指し、

プロジェクト名はデフォルトでは設定ファイルが置いてあるフォルダ名が自動的に付けられます

(例:/myapp/compose.yaml の場合は、myapp がプロジェクト名になる)

そのため、上述の通り、compose.yml ファイルごとにプロジェクトが作成されるため、もし2つのディレクトリ内に2つの別々の compose.yml を配置してしまうと、

プロジェクト名が重複してしまい、本当は b-compose.yml の操作を実施したかったのに、誤って b-compose.yml の操作を実施してしまうなどは発生します

したがって、複数の compose.yml を利用する場合は、compose.yml 上で name を利用し、compose.yml 毎にプロジェクトを分離する方法がよいかと思います

▼例

version: "3.9"
name: dood01 ★
services:
  web01:
    build:
      context: ./
      dockerfile: web/Dockerfile
    container_name: web01-container
    volumes:
      - ./app/src:/var/www/vhosts/www.example.com/public_html
    depends_on:
      - app01
    ports:
      - "80:80"

→ 上記だと dood01 がプロジェクト名になります

 

そのうえで、今回の構成を確認してみると、ホストOS上の nginx_php-fpm_docker  ディレクトリ内に docker-compose.yml が配置されており、それを利用して WebコンテナとAPPコンテナを起動しました

そのため、ホストOS上ではプロジェクト名が nginx_php-fpm_docker になっています

docker-compose ls
[root@dood01 nginx_php-fpm_docker]# docker-compose ls
NAME                   STATUS              CONFIG FILES
nginx_php-fpm_docker   running(2)          /root/nginx_php-fpm_docker/docker-compose.yml

 

次に、APPコンテナの /home/docker 上でプロジェクト名を確認してみます

docker compose ls
www-data@f45dbc30d49a:/home/docker$ docker compose ls
NAME                   STATUS              CONFIG FILES
nginx_php-fpm_docker   running(2)          /root/nginx_php-fpm_docker/docker-compose.yml

→ あれ? docker プロジェクトではない??

理由としては、今回 APPコンテナ内で docker-compose.yml を実行しておらず、

どうやら docker compose ls コマンドは docker.sock 経由で共有しているホストのデーモンを見にいくみたいなので、ホスト側の nginx_php-fpm_docker が表示されています

 

それでは、一度 プロジェクトを指定し、Webコンテナへ対してコマンドを実行してみます

docker compose -p nginx_php-fpm_docker exec web01 nginx -v
www-data@f45dbc30d49a:/home/docker$ docker compose -p nginx_php-fpm_docker exec web01 nginx -v
nginx version: nginx/1.25.0

→ Nginx のバージョンが表示されたので、問題なく動作してそうです

 

次に、Webコンテナを停止してみます

docker compose -p nginx_php-fpm_docker stop web01
www-data@f45dbc30d49a:/home/docker$ docker compose -p nginx_php-fpm_docker stop web01
[+] Stopping 1/1
 ✔ Container web01-container  Stopped
www-data@f45dbc30d49a:/home/docker$ docker compose -p nginx_php-fpm_docker ps
NAME              IMAGE                        COMMAND                  SERVICE   CREATED          STATUS          PORTS
app01-container   nginx_php-fpm_docker-app01   "docker-php-entrypoi…"   app01     55 minutes ago   Up 55 minutes   0.0.0.0:9000->9000/tcp, :::9000->9000/tcp

→ APPコンテナのみ起動しています

 

■最後に

いかがでしたでしょうか

正直これまでにdocker-composeのプロジェクトの概念を知らなかったので、最初はかなりはまりました、、、

ただ、一度理解すれば、そこまで複雑ではない + docker-compose の設計に幅を持たせることができると思ったので、今後は積極的に利用していきたいです

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA