Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

Docker Desktopの代わりにFinchでヤプリの開発環境を動かしてみた

概要

こんにちは。サーバーサイドエンジニアの窪田です。 先日、Finchという名前のOSSがAWSから発表されましたね!

github.com

aws.amazon.com

FinchはLinuxコンテナのビルドや起動等ができるコマンドラインクライアントで、 Docker Desktopに代わるコンテナ管理できるツールとして期待されています。 英単語のFinchは小鳥の総称の意味らしいです。ロゴも小鳥っぽいですね!

今回はFinchを触ってみると同時に、普段使っているヤプリのプロダクト群の開発環境は動かせるのか調べました。

ヤプリの開発環境

ヤプリでは以下のコンテナをdockerで管理しています。

  • nginx(web サーバ)
  • php-fpm (php アプリケーションサーバ)
  • MySQL
  • Redis
  • LocalStack
  • MailHog

また、人によっては

  • grpcサーバ(Goアプリケーション)
  • envoy
  • その他いろいろ

もdockerの上で動作させて開発しています。 自分はgrpcサーバについてはMacの上で起動させています。

docker-compose.ymlでこれらのサービス群を管理しています。 docker-compose.ymlの雰囲気は以下です。

version: '3.7'

services:
  app:
    platform: linux/amd64
    build: .
    shm_size: 256m
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - "8084:80"
    environment:
      SQS_ENDPOINT: http://localstack:4566
    networks:
      my_network:
    depends_on:
      - redis
      - mysql
  redis:
    image: redis:3
    networks:
      my_network:
    ports:
      - "6379:6379"
  mysql:
    platform: linux/amd64
    image: mysql:5.7
    volumes:
      - ./db/data:/var/lib/mysql
    networks:
      my_network:
    ports:
      - "13306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password

  localstack:
    image: localstack/localstack:1.0
    ports:
      - "4566:4566"
    networks:
      - my_network

networks:
  my_network:

内部情報が書かれていたので部分的に消していたり、書き換えたりしています。 あくまで雰囲気を感じ取っていただけたらと思います。

app serviceのbuild用DockerfileはRUNコマンドでphpやnginxのインストールを行い, CMDコマンドでwebサーバ、アプリケーションサーバを起動するというごく一般的な内容です。

これを

~$ docker-compose up

によって開発に必要なサーバ等を起動しています。

Finchを使ってみる

下準備

finchのインストールはGUIでreadmeに従い行いました。 紹介している他記事がたくさんあるので省略します。

~$ finch -v
finch version v0.1.0

でインストールが確認できました。

readmeに従い仮想マシンを起動します

~$ finch vm init

以降finch vm start, finch vm stopで仮想マシンの起動、停止は行えます。

finch compose upを試す

docker-composeはdockerと別にインストールが必要なのに対し、 Finchはcomposerをデフォルトで備えています。

docker-compose upの代わりに

~$ finch compose up --build

を実行すると...失敗しました(惜しい)。

対応したことを残します。

env fileは明確に指定する必要がある

.envrcなどで定義している環境変数を渡したい場合

finch compose up --env-file=.envrc

のように明示する必要がありました。

mysql:5.7 イメージについて、platform, uidを明示する必要がある

結論的には以下の変更をdocker-compose.ymlに対して行いました。

(略)
  mysql:
    platform: linux/amd64 // <-----追記
    image: mysql:5.7
    volumes:
      - ./db/data:/var/lib/mysql
    networks:
      my_network:
    ports:
      - "13306:3306"
    user: 1000:1000  // <-----追記
    environment:
      MYSQL_ROOT_PASSWORD: password
(略)

mysql:5.7のbaseはRHELで、defaultの最小uidである1000を指定しました。 指定しないと、コンテナ内部でroot権限が得られずpermission denied エラーが発生しました。

驚くことに、対応したのはこれらだけでした。 ほぼそのままdocker-compose.ymlを使うことができました。 MySQL, Redis, LocalStack等もdocker-compose upで起動した時と同様に開発環境で動かすことができました。 もちろんvolumeやnetworkも同じように使えます。

~$ finch volume ls
~$ finch network ls

で新規volume, networkが作成されていることを確認できました。

おまけ・その1: コンテナからホストへアクセスしたい時の注意

envoyを例に取ります。 ヤプリではgrpcサーバで提供されるプロダクトがあるのでenvoyが必須になります。 開発環境では、grpcサーバ(Goアプリケーション)をMacの上に立てて、その上流にenvoyをdockerで立てることがあります。 その場合、アクセスは外部-> envoy(on docker)-> grpcサーバ(on mac)の経路になります。 この時、使うenvoy.yamlは以下のようになります。

static_resources:
  listeners:
  -----------省略--------------
  clusters:
    - name: local_service
  -----------省略--------------
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: host.docker.internal
                      port_value: 50051

ポイントはaddress: host.docker.internalでホスト(今回の場合Mac)の50051ポートへ転送しています。 これをそのままFinchで使うと動きません。

Finchは内部的にLimaという仮想マシンを使っています。 github.com

そのため、Finchで使うためにはaddress: host.lima.internalを指定する必要があります。

static_resources:
  listeners:
  -----------省略--------------
  clusters:
    - name: local_service
  -----------省略--------------
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: host.lima.internal
                      port_value: 50051

おまけ・その2: Hot Reloadが効かない

これは試したみただけで、細かい原因までは辿り着けていませんが、Finchで起動したコンテナの上ではHot Reload(厳密にはファイル変更検知)が効きませんでした。 試したのは Goのair github.com

とNestjsというTypeScript FWのwatchモードで試しました。 docs.nestjs.com 結果的に両方の場合、docker-compose ではHot Reloadが効きましたがFinchでは効きませんでした。

airで試した際のdocker-compose.ymlとDockerfileは以下です。

version: '3'

services:
  app:
    platform: linux/amd64
    build: .
    working_dir: /var/work/go-container
    user: root
    volumes:
      - type: bind
        source: .
        target: /var/work/go-container
FROM golang:1.19.3-alpine

RUN go install github.com/cosmtrek/air@latest
RUN adduser docker -D

CMD ["air"]

volumeとしてマウントしていて、lessコマンド等で確認する限りファイル変更はされます。 また、サーバを再起動すれば変更は反映されるので、Hot Reloadさえ気にしなければ開発には全く支障はないと思います。 airはファイル変更を sys/unix packageで検知する仕様です。 pkg.go.dev このパッケージはシステムコールレベルまでアクセスして変更を検知していてその仕様とFinchのvolumeマウントの仕様を知る必要がありそうです。 この辺りは調べられたら別記事にまとめようと思います。

まとめ

AWSが発表して話題になっていたFinchですが、思ったよりも少ない手間で今開発環境で使っているdocker-compose.ymlに対応させることができることがわかりました。 今後も動向を追っていこうと思います。 ヤプリでは開発環境はdockerで構築しています。(というかサービスが多すぎてdockerがないと厳しい。) 本番サービスについても大部分がコンテナで運用しています。 このあたりの話に興味が少しでもあればぜひカジュアル面談にお越しください。

open.talentio.com

Copyright © 2021 Yappli, Inc. All rights reserved