ぽよメモ

レガシーシステム考古学専攻

nginxとdocker-genとその他を使って良い感じにする(2)~gitlab構築~

poyo.hatenablog.jp

前回の続きです.今回はgitlabの構築をしたいと思います.

環境

前回と同じ

構築したい環境

gitlab.hoge.comという感じのサブドメイン,かつhttpsでgitlabにアクセスできるようにする.

前準備

前回で構築した環境が動いていれば問題ないです.

gitlabのコンテナを建てる

Gitlabのdockerコンテナ構築にはsameersbn/docker-gitlabがよく用いられているように思いますが,公式のコンテナがあるのでそっちを使っていきたいと思います.

ディレクトリ構成は以下の様にします.

.
├── config
├── data
├── docker-compose.yml
└── logs

設定

version: "2"
services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    container_name: gitlab
    volumes:
      - ./data:/var/opt/gitlab
      - ./config:/etc/gitlab
      - ./logs:/var/log/gitlab
    restart: always
    environment:
      VIRTUAL_HOST: gitlab.hoge.com
      VIRTUAL_NETWORK: shared
      VIRTUAL_PORT: 80
      LETSENCRYPT_HOST: gitlab.hoge.com
      LETSENCRYPT_EMAIL: hoge@mail.hoge.com
      GITLAB_OMNIBUS_CONFIG: |
        external_url "https://gitlab.hoge.com"
        nginx['listen_port'] = 80
        nginx['listen_https'] = false
        nginx['proxy_set_headers'] = {
          "X-Forwarded-Proto" => "https",
          "X-Forwarded-Ssl" => "on"
        }
        gitlab_rails['time_zone'] = 'Asia/Tokyo'
    networks:
      - shared

networks:
  shared:
    external:
      name: internal_shared

gitlabのhttps化には色々手段が考えられると思いますし,直接gitlabを外部に晒す方法であれば直接gitlabに対してletsencryptで取得した証明書を食わせるべきですが,今回はそれらを全てフロントエンドのnginxに任せてしまいます*1

通常external_url "https://gitlab.hoge.com"を指定すると証明書が要求されますが,以降のnginxに関する設定をすることでリバースプロキシにそれらの処理をゆだねることが出来ます.

起動

$ docker-compose up

gitlabはかなりメモリを食うようです.実験のためにMac上のVagrantで起動しようとしたときはひたすらエラーでなんともなりませんでしたが,サーバ上ではうまく動いてくれました.
初回起動時には様々な設定を行うようでそこそこの時間がかかり,それまではアクセスしてもエラーが帰ってくるだけになります.

httpsでアクセスできるようになったら成功です.初回ログインに成功したらアカウントの登録を止めておきましょう.

うまくいってないこと

メールの設定もしたのですが確認メールが送られてきません.ルータのログも確認しましたが特にそこでフィルタリングしているわけではなく,どうもgitlabの内部のエラーで送れていないようです.何度か設定をいじくり回したのでそこで何かおかしくなったような気もするのですが…

まとめ

ずっとgithubに頼っていましたがどうしてもgitlabのCI/CDをためしてみたかったのでインストールしました.簡単に起動できて最高な時代になったなぁ…

*1:なぜかというと最初は前回作製したcertsディレクトリをマウントしてやってみたのですがどうもうまく行かなかったためです.

nginxとdocker-genとその他を使って良い感じにする(1)

jwilder/nginx-proxyという超便利コンテナがあるのですが,こいつは/var/run/docker.sockをReadOnlyとはいえ外側に晒すコンテナにマウントすることになり怖いので,推奨されているようにjwilder/docker-gennginxを分けて同様の環境を構築します.

環境

  • Ubuntu Server 16.04LTS
  • Docker version 1.13.0
  • docker-compose version 1.8.0

構築したい環境

macvlanドライバを用いたフロントのnginxへの静的IPアドレスの割り当て,及びdocker-genとJrCs/docker-letsencrypt-nginx-proxy-companionの機能を用いた各コンテナへのサブドメインの割り当てとSSL対応.(2)でgitlabを立ち上げて完成とします.

前準備

静的アドレス割り当て

まず,うちの環境ではこれまでYAMAHA RTX1200を使って,LXCで構築した外側に晒すコンテナ群のセグメントを分けて運用していました.つまり,それぞれのコンテナに対してブリッジを用いて静的なIPアドレスを割り当てていました.そしてルータのIPマスカレードでそれぞれのコンテナへとパケットを通していました.
しかしDockerで静的なIPを割り当てる方法を検索しても,直接NICの下にぶら下げる方法はあまり出てきませんでした.

そこで先輩に教えていただいたのがdocker networkのmacvlanドライバです.

github.com

これを用いてdocker networkを作り,それぞれのコンテナへとホストに割り当てられているものと同じ空間の静的なipv4アドレスを割り当てることが出来ました.

まず,ホストのNIC(何も使われていない余っているもの.以下hoge)をプロミスキャスモードにし,network createします.

$ docker network create --driver macvlan \
    --subnet=xxx.xxx.x.x/24 \
    --gateway=xxx.xxx.x.y \
    -o parent=hoge dmz_nw

docker-composeでのipの割り当て方は以下の様にします.

version: "2"
services:
  front_test:
    image: nginx
    container_name: front_test
    networks:
      dmz_nw:
        ipv4_address: xxx.xxx.x.z
networks:
  dmz_nw:
    external:
      name: dmz_nw

ブラウザからxxx.xxx.x.zにアクセスしてWelcome to Nginxが出てこれば成功です.

各コンテナを繋ぐネットワークの作製

macvlanドライバを用いると,gateway(ルータ)に直接問い合わせをするためdockerの名前解決は使えない*1ため,docker-genの機能を活用するために別のbridgeドライバを用いたnetworkを作製します*2

$ docker network create --driver bridge \
    -o "com.docker.network.bridge.name"="shared" \
    shared

nginxとdocker-genを組み合わせる

ディレクトリ構造は以下の様にして進めます.

.
├── docker-compose.yml
├──proxy
│   ├── certs
│   ├── conf
│   │   └── default.conf
│   ├── html
│   ├── templates
│   │   └── nginx.tmpl
│   └── vhost
│        └── default
└── web
    └── Dockerfile

nginxの設定

docker-compose.ymlに記述していきます.

version: "2"
services:
  proxy:
    image: nginx
    container_name: proxy # そのままではコンテナ名が面倒なことになるので指定
    volumes:
      - ./proxy/html:/usr/share/nginx/html:rw
      - ./proxy/conf:/etc/nginx/conf.d
      - ./proxy/vhost:/etc/nginx/vhost.d
      - ./proxy/certs:/etc/nginx/certs:ro # ReadOnlyでマウント 
    restart: always
    networks:
      shared:
        aliases:
          - proxy
      dmz_nw:
        ipv4_address: xxx.xxx.x.N
networks:
  shared:
    external:
      name: shared
  dmz_nw:
    external:
      name: dmz_nw

/usr/share/nginx/htmlrwでマウントしないとなぜかJrCs/docker-letsencrypt-nginx-proxy-companionがエラーを吐きました.

docker-genの設定

本来はnginx-proxyに含まれているnginx.tmplファイルが必要となるので落としてきます.

$ curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > ./proxy/templates/nginx.tmpl

nginxの設定に追記していきます.

version: "2"
services:
  proxy:
  # 省略
  nginx-gen:
    image: jwilder/docker-gen:latest
    container_name: nginx-gen
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro # ReadOnlyでマウント
      - ./proxy/templates/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro # tmplファイルをマウント
    volumes_from:
      - proxy
    restart: always
    entrypoint: /usr/local/bin/docker-gen -notify-sighup proxy -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
    networks:
      - shared
networks:
  # 省略 

letsencryptの設定

version: "2"
services:
  proxy:
  # 省略
  nginx-gen:
  # 省略
  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nginx-letsencrypt
    volumes_from:
      - proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro # ReadOnlyでマウント
      - ./proxy/certs:/etc/nginx/certs:rw
    environment:
      NGINX_DOCKER_GEN_CONTAINER: nginx-gen
    depends_on:
      - nginx-gen
    restart: always
    networks:
      - shared
networks:
  # 省略 

webサーバをぶら下げてみる

以下,webサーバをぶら下げるアドレスをwww.hoge.comとして進めます.

設定

version: "2"
services:
  proxy:
  # 省略
  nginx-gen:
  # 省略
  letsencrypt:
  # 省略
  web:
    build: ./web
    container_name: web
    environment:
      VIRTUAL_HOST: www.hoge.com
      VIRTUAL_NETWORK: shared
      LETSENCRYPT_HOST: www.hoge.com
      LETSENCRYPT_EMAIL: hoge@mail.hoge.com
    depends_on:
      - nginx-gen
      - proxy
    restart: always
    networks:
      - shared
networks:
  # 省略 

webディレクトリ以下のDockerfileを編集しますが,これはgithubリポジトリに自分のwebサーバの静的ファイルを置いているためで必須ではないです.

FROM nginx:latest

RUN apt update && \
    apt install -y git && \
    rm -r /usr/share/nginx/html && \
    git clone https://github.com/pddg/poyo_web.git /usr/share/nginx/html

立ち上げてみる

$ docker-compose up --build

最初letsencryptでの証明書の取得に時間がかかります.うまく立ち上がったっぽい雰囲気を感じたらwww.hoge.comにアクセスしてみて,うまく表示されれば完了です.

まとめ

RTX1200でフィルターを使ってアクセスに制限をかけているとはいえ,macvlan以下にぶら下げたコンテナは何の防御もしていないため,もう少し何かするべきかもしれませんがとりあえずはここまで.
かなり身構えてやり始めましたが,2~3時間で思っていたものが出来上がったので良かったです.

今回は全て同じdocker-compose.ymlに記述しましたが,上記で使用したsharedネットワークにさえ接続すれば,docker runでも,他のdocker-compose.ymlでも,VIRTUAL_HOSTなど各種の環境変数を与えることでサブドメインの割り当てが出来ます.

もう少ししたらgitlabを立ち上げてgitlab.hoge.comへとhttpsでアクセスできるようにした記事を書きたいと思います.

続き書きました

poyo.hatenablog.jp

*1:これは未確認なので実は使えるとかだったら教えてください…

*2:ここに出てくる"com.docker.network.bridge.name"というオプションはホストでbrctl showやifconfig等したときに表示されるインターフェース名を自動生成された名称ではなく,自分で付けた名前にするオプションです.

MacのTwitterクライアントが一切繋がらなくなったのを解決した話

TweetDeckが繋がらなくなったのが最初で,以降夜フクロウもダメになり,最近は公式クライアントでなんとかしていたのですが,ついにそれすらも全く繋がらない状態になってしまったため,さすがに本腰を入れようかと思い色々やったら思ったよりもハマってしまったという話です.

環境

症状

  1. Twitterクライアントを起動しても全く読み込まない
  2. ブラウザ等は正常にTwitterに接続できる
  3. コンソール等からpingしたりtracerouteしてもちゃんとtwitter.comに到達できる
  4. プロキシ環境下でもなんでもない自宅のWi-Fi環境下で起きる
  5. そのWi-Fiに繋がっている他の端末でも正常にTwitterが使える

原因究明

まずWireshark*1でパケット解析をしてみることに.とりあえずブラウザ等を閉じて,http || sslでフィルタリングしてみると,Twitterクライアントを起動しても一切パケットが飛んでいない(!)ことが分かりました.
名前解決が上手くいっていないのではということで,dnsでフィルタリングしてみましたが,正常に解決している模様.

しかし,フィルタを取っ払って見てみると,どうも大学のdnsサーバらしきアドレスに対してひたすら"TCP Retransmission"*2している模様.おそらくDNS周りのゴミが残っていて正常に通信できていないのではという仮説を立て色々やってみました.

試行錯誤

試行1: 再起動

何か困ったら再起動.しかし効果無し.

試行2: DHCPリース更新

効果無し.

試行3: ローカルのDNSキャッシュをクリア

通常ネットワークの切断時に行われるはずですが,一応

$ sudo killall -HUP mDNSResponder

効果無し.

試行4: ネットワーク設定からDNSに8.8.8.8を追記

効果無し.

解決: ネットワーク設定から「自動プロキシ検出」をオフに

正直半ば諦めていたのですが,たまたま気付いて切ってみたら上手くいったので心底驚きました…
検出だけなら問題ないだろうと思っていたのですが,もう一度オンにするとまた接続できなくなっていたので,おそらくこれが原因と思われます.

ブラウザ等他のものが正常動作していたせいで何が原因なのかの切り分けが難しく,かなりハマりました.とはいえ,プロキシ検出を切ってしまうとまた大学に行くたびにこれをオンにしないといけなくなって面倒なので何かしら対策はしたいところ…

まとめ

Twitterクライアントがつながらないときはプロキシ検出を切れ. 」

今までのOS Xでは特に問題がなかったのでmacOS Sierraから…?それとも僕の環境に特異的な何かなのでしょうか…とはいえ治って良かったです.

*1:ja.osdn.net

*2:パケットの再送.通常ネットワークの状態が悪いときとかに起こるものらしい.