🐳

Dockerについて実用面を中心にできるだけ短く【バックエンドエンジニア向け】

2024/03/07に公開

前置き

最近よく聞くDockerというものについて、詳細に説明を書いてくれている記事は多くあるものの、私の集中力では説明が長すぎて頭に入ってこない場合が多かったので、出来るだけ短く要点を押さえながらまとめてみたいと思います。

書かないこと

動作原理や類似システムとの比較など
インストールの方法や初期設定等の予備知識

書くこと

ユースケース
Dockerを使うための考え方

ユースケース

いくつかあると思いますが、私のユースケースとしては、

  • 同一構成の実行環境を複数のデバイスで作成する
  • かつ、出来るだけ簡単にそれを実現する

ために使いました。

オーソドックスな例でいうと、
apache+PHP及びmySQLをDockerで立ち上げ、ブラウザからlocalhostでアクセスできるようにする、というような具合です。

各種ミドルウェアを普通にインストールしても良いのですが、そうすると、

  • インストールのタイミングによってバージョンが違う可能性がある
  • 異なるバージョンのミドルウェアで動作検証したい場合などにわざわざ再インストールするのが面倒

というおおよそ二つの問題が発生します。
Dockerを使う事で両方の問題を解決できます。

Dockerを使う上で重要と思われる要素

端的に結論を書くと、

  • ホストマシンとコンテナ間のファイル共有
  • コンテナへのtcp/ip接続
  • ホストマシンからコンテナ内のコマンドの実行
  • docker desktopは慣れてきてから使うべき

の4つです。
細かい事は他に色々あると思いますが、とりあえず上から3つが解ればシンプルに使う分には困らないと思います。

docker desktopについてはGUIなのでコマンドライン版より簡単そうに見えるかもしれませんが、私の所感では、構成ファイルやコマンドが隠蔽されるため、内部的に何がどう動いているかの理解を深めるには向いていないと感じました。

具体的な設定例

docker-compose.yml
version: '3'
services:
  php:
    build:
      context: ./docker/app
    ports:
      - "80:80"
    volumes:
      - "./docker/app/apache2/apache2.conf:/etc/apache2/apache2.conf"
      - $HOME/www/html:/var/www/html
    depends_on:
      - mysql

  mysql:
    build:
      context: ./docker/mysql
      dockerfile: Dockerfile
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=pass
php/Dockerfile
FROM php:8.2-apache

COPY php.ini /usr/local/etc/php/php.ini

RUN apt-get update \
  && docker-php-ext-install mysqli mbstring

EXPOSE 80
mysql/Dockerfile
FROM mysql:8.0

EXPOSE 3306

これらのファイルを用意して、docker-compose.ymlが設置してあるディレクトリで起動コマンドを実行する。

docker compose up

これだけでapacheとmysqlサーバーが起動します。

WEBサーバーやmysqlサーバーがこうやって起動できるのは分かったけど、 apacheのconfの変更や具体的な接続はどうやったら出来るんだい? と思いませんか?私は思いました。

dockerのインストールやコンテナの起動などの説明をしてくれている記事は結構あるのですが、現場が具体的に知りたいであろう事を書いている記事は思いの外少ないようなので、このあたりの事を中心に書いていきます。

ホストマシンとコンテナ間のファイル共有

構成例のvolumesの設定がそれを実現するためのものとなります。

:の左側がホストマシンのパス、右側がコンテナ内のパスです。
このように、ホストマシンとコンテナ間でパスをマッピングします。
Linuxのfstabの設定のようなものと考えるとしっくりきます。
内部的な挙動はよくわかりませんが、コンテナ側に元々存在するファイルの場合はこの設定によって上書きされるものと思われ、この仕組みによってミドルウェアのconfファイルを任意に変更できそうです。
また、httpのdocumentrootをホストマシン上のディレクトリとマッピングすることで、htmlの編集がホストマシン上で可能になります。

コンテナへのtcp/ip接続

コンテナがサーバー用途の場合、ホストマシンからコンテナに接続したい場合があります。
その場合、コンテナのIPアドレスは何になってるのだろう? と思いませんか?私は思いました。

結論をいうと、ホストマシンからコンテナへのアクセスはlocalhostで可能です。
ただし、windowsでWSLを使っている場合は状況がややこしくなります。後述。

コンテナからコンテナへの接続

phpコンテナからmysqlコンテナへ接続する場合、localhostでは接続できません。
コンテナ名で接続します。内部的な理屈はよくわかりませんが、擬似的にhostsが設定されているような状態と考えるとしっくりきます。
例:
new mysqli('mysql',...)

WSL(2)と連携している場合

WSL内で立ち上げたコンテナの場合でも、ホストマシンからの接続は変わらずlocalhostでの接続となります。
WSLのlinuxそのものは別のIPアドレスが割り当てられるのになんで?と思いませんか?私は思いました。

これは予測ですが、WSL内で立ち上げたコンテナもwindows自体をホストとして起動しており、WSL内での起動とwindows(docker desktop)からの起動に差異がないのかもしれません。

ホストマシンからコンテナ内のコマンド実行

docker execコマンドでコンテナ内のプログラムを起動できます。bashなどを実行してやるとシェルが起動し、コンテナ内部を探索することができます。

コンテナというものがどう動いているのか、細い事はよくわかりませんが、linuxなどのOSが中に入っており、その上でmysqlなどが動いているようです。ただし、コンテナの構成によって、インストール?されているコマンドは違うようで、pathが通ってない場合もあり、絶対パスでコマンド実行しなければならないケースがあったりしました。

まとめ

他にも色々と機能があるのだとは思いますが、とりあえず実用面の導入としてはこのあたりをおさえておけば後はどうにでもなるかなと思います。

MySQL等のミドルウェアをデバイス毎に個別にインストールして設定するのは結構大変ですが、Dockerなら構成ファイルを配布して実行するだけでインストールができますし、要らなくなったらコンテナを落とすだけという手軽さもあります。
この辺りの手軽さとポータビリティの高さが便利なところなのかなと思いました。

Discussion