この記事は AWS Fargate Advent Calendar 2017 の19日目の記事です。

cloudpack大阪の佐々木です。
Fargateでコンテナ間通信させるときの話です。

概要


Docker環境で、コンテナ間で通信させるためにLinkという機能があります。1

ECS上でLink機能を使用しているタスク定義を、Fargateで実行しようとしてもエラーになって動きません。

実行結果


まず簡単な例として、Wordpress + MySQLという構成があるとします。2
WordpressコンテナとMySQLコンテナがあって、Wordpressの方にLinkを指定することで、mysqlという名前で通信できるようになります。

docker-compose.yml

version: '2'
services:
  wordpress:
    image: wordpress
    ports:
      - "80:80"
    links:
      - mysql
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: password

ECSであれば、この構成で問題なく動くんですが、Fargateで起動させると下のようなエラーになります。

$ ecs-cli compose service up --launch-type FARGATE                                          
WARN[0000] Skipping unsupported YAML option...           option name=networks
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=mysql
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=wordpress
ERRO[0001] Error registering task definition             error="ClientException: Links are not supported when networkMode=awsvpc.\n\tstatus code: 400, request id:  axxxxx-e39c-11e7-a22a-xxxxxxxxx" family=wordpress
ERRO[0001] Create task definition failed                 error="ClientException: Links are not supported when networkMode=awsvpc.\n\tstatus code: 400, request id:  axxxxx-e39c-11e7-a22a-xxxxxxxxx"
FATA[0001] ClientException: Links are not supported when networkMode=awsvpc.
    status code: 400, request id: axxxxx-e39c-11e7-a22a-xxxxxxxxx

つまりFargateではLink機能はサポートされていないということです。

AWSのドキュメントには下記のように記載されてました。

Only supported if the network mode of a task definition is set to bridge.

http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html

Fargateのネットワークモードは awsvpc になるので、この機能はサポートされてないと。

解決方法

色々見てみたんですが、Link機能の代替となるようなものを見つけられなかったので、@riywo さんに質問してみたところあっさり教えてもらいました。

https://qiita.com/sawanoboly/items/2766c8b0760ad9f9be99

なるほど・・・

ん? 別のコンテナの起動しているポートもlocalhostとして見えるのか?

確認してみました。)

確認

同じタスク定義内に、もう一つ別にssh接続用のコンテナを起動して、そのコンテナからどう見えるのかを確認してみました。
ssh接続用コンテナの作り方はこのへんを参考にしました。

https://qiita.com/sawanoboly/items/2766c8b0760ad9f9be99

docker-compose.yml

version: '2'
services:
  sshd:
    image: taishin/amazonlinux-sshd
    ports:
      - "22:22"
  wordpress:
    image: wordpress
    ports:
      - "80:80"
    # links:
    #   - mysql
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: password

起動して、sshログインし、確認してみます。

-bash-4.2# netstat -nl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:3128                0.0.0.0:*                   LISTEN
tcp        0      0 :::3306                     :::*                        LISTEN
tcp        0      0 :::3128                     :::*                        LISTEN
udp        0      0 0.0.0.0:68                  0.0.0.0:*
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node Path
unix  2      [ ACC ]     STREAM     LISTENING     17520  /var/run/mysqld/mysqld.sock

おー 確かに別コンテナが使用しているTCP/80、TCP/3306もローカルでLISTENしてます。

ブラウザでアクセスしてみます。

データベースがないってエラーにはなってますが、MySQLへの接続は問題なくてきているようです。
ちなみに データベースのホスト名 のところは localhost ではなく、 127.0.0.1 と入力しないとエラーになります。
理由はこちら

https://qiita.com/TanukiTam/items/f6a08740d0fcda0db7be

完成形

最終的に作成した docker-compose.yml は下記のようになります。

docker-compose.yml

version: '2'
services:
  wordpress:
    image: wordpress
    ports:
      - "80:80"
    environment:
      WORDPRESS_DB_HOST: 127.0.0.1
      WORDPRESS_DB_PASSWORD: password
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: password

WordPressコンテナの環境変数はこちらを参照
https://hub.docker.com/_/wordpress/

ecs-cli compose service up --launch-type FARGATE                                          [15:20:08]
WARN[0000] Skipping unsupported YAML option...           option name=networks
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=wordpress
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=mysql
WARN[0000] Skipping unsupported YAML option for service...  option name=networks service name=sshd
INFO[0001] Using ECS task definition                     TaskDefinition="wordpress:11"
INFO[0002] Created an ECS service                        service=ecscompose-service-wordpress taskDefinition="wordpress:11"
INFO[0002] Updated ECS service successfully              desiredCount=1 serviceName=ecscompose-service-wordpress
INFO[0018] (service ecscompose-service-wordpress) has started 1 tasks: (task xxxxxxx-46f4-4b29-b09f-5484982bd294).  timestamp=2017-12-18 06:22:45 +0000 UTC
INFO[0124] Service status                                desiredCount=1 runningCount=1 serviceName=ecscompose-service-wordpress
INFO[0124] (service ecscompose-service-wordpress) has reached a steady state.  timestamp=2017-12-18 06:24:31 +0000 UTC
INFO[0124] ECS Service has reached a stable state        desiredCount=1 runningCount=1 serviceName=ecscompose-service-wordpress

ブラウザでアクセスすると、

正常に動きました。

まとめ

Fargateでコンテナ間で通信させたい場合は、Link機能は使えないけど、localhost:ポート番号でアクセスできる!


1. Dockerのlink機能は非推奨になってるみたいです。
https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/

2. Fargateではボリュームマウントもできないので、データ永続化させるようなMySQLコンテナを動かすってことはあまりないかと思いますが・・・

元記事はこちら

AWS Fargateでコンテナ間通信させたいとき