Dockerコンテナ単体にネットワークアクセスする

docker-composeばかり使っていたら、dockerへのネットワーク接続の仕方を忘れていたのでメモっておく。 ググったほうが速いかもしれないやつ。

docker run -d -p 80:3000 -t a
  • -p ポートのマッピング
  • -d デタッチ
  • -t 実行するイメージのタグ

passport/expressのサーバとOIDCプロバイダーの間にProxyを通す

インターネットへのアクセスにプロキシが必要な社内ネットに、Webサーバを立てて、Auth Code FlowでOIDCの認証を利用しようとすると、 Webサーバ(OIDCのクライアント)とOIDCプロバイダーの間にもProxyを通しておく必要がある。

例えば、expressでAzureADのOIDC認証を利用しようとすると、passportおよびpassport-adでOIDCの認証を利用できるのだが、 expressとかpassportが裏で行うOIDCプロバイダーへのアクセスにもproxyを通す必要がある。

しかし、いわば勝手に通信をしてしまうので、直接プロキシを通しずらいという問題がある。

そこで、global-agentというのを試した。 ほかにもいくつかあったが、簡単に使えてWeekly Downloadがまぁまぁ多かったのが採用の理由。

使い方は、公式に書いてある通りなのだが、一応メモしておく。 他の使い方は公式を参照のこと。

  1. global-agentを追加する。

sh yarn add global-agent

  1. GLOBAL_AGENT_を頭につけたプロキシの環境変数を設定しておく。
export GLOBAL_AGEMT_HTTP_PROXY=$HTTP_PROXY
export GLOBAL_AGEMT_HTTPS_PROXY=$HTTPS_PROXY
export GLOBAL_AGEMT_NO_PROXY=$NO_PROXY
  1. 起動するコードに以下のimportを追加しておく。
import 'global-agent/bootstrap';

global-agentによってnodejsのhttpまたはhttpsモジュールの接続をproxyを介するようになる。 passportをはじめとする、大体のモジュールはhttp/httpsモジュールを使って通信をしている。

なので、Azure ADのOIDC認証も、プロキシを越えて利用できるようなるということ。

Spring JDBCを生で試す。

Spring JDBCについて調べると、まぁ、Spring Bootでの利用の話ばかりなので、Spring Bootなしで利用するのはどうするんだ、というのを試した。 普通に簡単。

Gradleから最低限必要な依存関係を抜き出すと以下。

dependencies {
    implementation 'mysql:mysql-connector-java:8.0.22'
    implementation 'org.springframework:spring-jdbc:5.3.1'
}

で、以下のような感じでコードを書けばクエリを叩ける。

public class Main {

    public static DataSource mysqlDataSource() {
        var username = "user";
        var password = "pass";
        var host = "127.0.0.1";
        var port = 3306;
        var database = "db";

        var dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl(String.format("jdbc:mysql://%s:%d/%s", host, port, database));
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    public static void main() {
        var dataSource = mysqlDataSource();
        JdbcTemplate template = new JdbcTemplate(dataSource);

        var list = template.queryForList("show tables", String.class);
        for (var e : list) {
            System.out.println(e);
        }
    }
}

Gitのサブモジュール操作

ググれば出てくるんだけど、頻繁に使うので、自分でもメモしておく。

Gitのサブモジュール

サブモジュールを含むプロジェクトのClone

git clone --recursive <URL>

サブモジュールの追加

git submodule add <URL> <path(optional)>

サブモジュールの削除

git submodule deinit -f <name>
git rm -f <name>
rm -rf .git/modules/<name>

サブモジュールの更新

git submodule update --init --recursive

初等セルオートマトンとライフゲームで遊ぶ。

だいぶ前にふと立ち寄った大学生協で買ったものの、ろくに読んでなかったセルオートマトンの本を読みつつ、遊んでみた。 今回遊んだセルオートマトンは初等セルオートマトンという単純なものだが、離散数学の面白さに少しふれられた気がする。

この初等セルオートマトンの各ルールやパラメータを気軽に試せるデモを作成して以下に公開した*1。READMEから主なRuleへのリンクを張っている。 github.com

ちなみに、初等セルオートマトンとはなんぞやという話を簡単にしておく。自分の理解は以下。

  • 一次元セルオートマトンで、セルの集合は1次元格子状に配置する。
  • セルの状態は0と1のみの最も単純なものを対象とし、0は白、1は黒で表現する。*2
  • セルの状態は離散的な時間間隔で変化し、セルの状態変化は同時にすべてのセルに対して行われる。*3
  • i番目のセルの時刻tにおける状態は、時刻t-1における、i-1番目のセルの状態とi番目のセルの状態とi+1番目の状態によって決定的に決まる。*4*5
  • セルの状態遷移関数は、決定的なものであれば256種類しかなく、Rule0からRule255として区別されている。
  • 状態遷移関数の定義次第では、規則性をもったり(Rule 1)、完全にランダム(Rule 30)になったり、周期性を持ったり収束したり(Rule 184)変化する。
  • 完全にランダムな状態変化*6を簡単に生成できるので、暗号などへの応用も研究されているらしい。*7
  • 基本的にはセルの数を有限と仮定する場合は境界条件に留意する必要がある。周期境界条件を用いれば可逆性や周期性が確認できる*8

それから、2次元セルオートマトンということで、ライフゲームも作ってみた。これも別に簡単なのに動かしたらいきなりそれっぽく動いて面白かった。

ma38su.github.io

動き方は以下。

  • ムーア近傍8セルのうち、3セルが生きていれば、次は生きる。
  • セルが生きていて、ムーア近傍8セルのうち、2セルが生きているとき、次は生きる。
  • 上記以外のセルは死ぬ。

*1:サーバサイドなしだと、GitHub Pagesで運用できてお手軽なので最近はこのスタイル。

*2:一般にはk以上の状態をもつものもある。

*3:状態変化は順序による影響を受けない。

*4:この状態を決める関数を遷移関数という

*5:時刻tの状態が、時刻t-1の状態のみから決まるオートマトンを1次オートマトンといい、時刻tの状態が、時刻t-1と時刻t-2の状態のみから決まるオートマトンを2次オートマトンというらしい。

*6:ランダム性は検定で検証済みとのこと

*7:現在のステータスまでは調べてない。

*8:固定の境界条件だと可逆性は確認できないケースもある

AWS EC2のAmazon LinuxにSSMでSSH接続する。

SSMを使うと、プライベートネット内のEC2など、通常踏み台サーバが必要なサーバに直接接続できる。

ググればいっぱいでてくるが、自分が実際にやってみた手順を残しておくのはやっぱり大事だなぁと思ったので残しておく。

  • 最新のAmazon Linuxを選択してインスタンスを生成する。
  • 生成したインスタンスを以下の通り設定しておく。
    1. インスタンスのセキュリティグループは、HTTPS(ポート443)のインバウンドを許可する。
    2. AmazonSSMManagedInstanceCoreのIAMポリシーをアタッチしたIAM Roleを割り当てる。
  • 接続したいローカルPCの設定を済ませる。
    1. PCにAWS CLIをインストールする。
    2. aws configureを実行してユーザ情報を設定しておく。
    3. Session Manager Plugin をインストールしておく。
  • SSMで、EC2のSSH(ポート22)をローカルの適当なポート(例えば10022)にポートフォワーディングする。
aws ssm start-session --target i-XXXX \
  --document-name AWS-StartPortForwardingSession \
  --parameters 'portNumber=22, localPortNumber=10022'
  • 別のターミナルからSSHを張ればよい。SSMを使わないときと同じだが、SSHにはEC2作成時のキーペアは必要。
ssh -i .ssh/xxx.pem -p <port> ec2-user@localhost

公式 https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-sessions-start.html

Javascriptで任意の変数名に分割代入する

変数名が重複する場合とか変数名を変えて分割代入したいときは以下でできる。

const data = {
  month: '10', year: '2020'
}

const { month: thisMonth, year: thisYear } = data;

console.log({ thisMonth, thisYear });

さらに初期値も設定できる。

const response = {
  data: [
    1, 2, 3, 4, 5
  ]
}

const { data: array = []} = response;
console.log(array);

ちなみにパッケージからインポートするときの名前を変えるのはasだったりする。

import { Menu as MenuIcon } from '@material-ui/icons'

特種な演算子とかこういうのとか、ググらビリティが良くないので忘れると困る。