[Docker] Dockerコンテナ同士で仮想シリアルポートをつないでみる。

2018年9月10日月曜日

Docker linux socat

socatで仮想シリアルポート

socatを使うと、以下のような感じで、仮想シリアルポート同士の通信ができる。

$ socat pty,raw,echo=0,link=/dev/ptty0 pty,raw,echo=0,link=/dev/ptty1
$ ls /dev/ptty*
/dev/ptty0 /dev/ptty1

一方のターミナルでptty0から読み込む。
$ cat </dev/ptty0

もう一方のターミナルでptty1に書き込む。
$ echo foo >/dev/ptty1

パイプと違って双方向通信なので、逆もできる。

Dockerコンテナではどうか?

Dockerコンテナ同士で似たようなことができないだろうか。
socatを使ってやってみよう。

Docker Compose

コンテナはserver1とserver2を作る。

docker-compose.yml
version: "2"
services:
  server1:
    build:
      context: .
      dockerfile: Dockerfile-socat
    tty: true
  server2:
    build:
      context: .
      dockerfile: Dockerfile-socat
    tty: true
alpine + socatを使う。

Dockerfile-socat
FROM alpine:latest
RUN apk add --update socat && rm -rf /var/cache/apk/*

コンテナ起動
$ docker-compose up -d

コマンド実行手順

サーバ間でコマンドを実行する順番がポイントなので、注意しよう。

[1] server1
まずはserver1側にログイン
$ docker-compose exec server1 sh

待ち受けるTCPサーバを立ち上げる。
これで、ポート1234で待ち受けて、接続すると /dev/ptty0に転送される。
# socat tcp-l:1234,reuseaddr pty,raw,echo=0,link=/dev/ptty0 &
# ls /dev
console  fd       mqueue   ptmx     random   stderr   stdout   urandom
core     full     null     pts      shm      stdin    tty      zero

この時点ではまだ、/dev/ptty0はできていない。

[2] server2
次にserver2からserver1につなげる。

server2にログイン
$ docker-compose exec server2 sh

# socat pty,raw,echo=0,link=/dev/ptty0 tcp:server1:1234 &
# ls /dev
console  full     ptmx     random   stdin    urandom
core     mqueue   pts      shm      stdout   zero
fd       null     ptty0    stderr   tty

これで、sever2の/dev/ptty0とserver1の1234ポートがつながった。

server2で上記のコマンドを実行した後に、server1側のターミナルを見ると、/dev/ptty0ができているのがわかる。
どうやら、接続を受け付けてから仮想端末が作られる模様。

# ls /dev
console  full     ptmx     random   stdin    urandom
core     mqueue   pts      shm      stdout   zero
fd       null     ptty0    stderr   tty

読み書きしてみる。

[1][2]の手順で、/dev/ptty0 同士が接続されたので、読み書きしてみよう。

server1
# cat </dev/ptty0

catで待ち受け。

server2
# echo foo >/dev/ptty0

これで、server1側に foo が出力される。