Docker おぼえがき

Be careful it's optimized only for me so the format probably doesn't make sense to you.

Docker

Build docker image without cache with a Dockerfile of the current directory with a name identiproxy with a tag 0.1

docker build --no-cache -t identiproxy:0.1 .

Stop and remove all running containers

docker ps -qa | xargs docker rm -f

Machine

Create a machine using generic (ssh) driver against 10.0.1.211 with a name "n1".

docker-machine create --driver generic --generic-ip-address=10.0.1.211 n1

https://docs.docker.com/machine/drivers/generic/#example Or against DigitalOcean

docker-machine create --driver digitalocean --digitalocean-access-token d40576... identihost-do

Others

Switch machine context

eval `docker-machine env n1`

Show machine ip address

docker-machine ip n1

Compose

https://docs.docker.com/compose/compose-file/https://docs.docker.com/compose/compose-file/#compose-file-structure-and-examples

Swarm

Initalize manager

docker-machine ssh n1 \
    docker swarm init --advertise-addr 10.0.1.211

# Remember the output command line

Join as a worker

docker-machine ssh n2 \
    docker swarm join --token SWMTKN... 10.0.1.211:2377

List swarm nodes

docker-machine ssh n1 docker node ls

ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
cfy4gr1s6b2dbz13fuxp7b8pd *   n1                  Ready               Active              Leader
nen91w96s0huyregcvtwgn2dx     n3                  Ready               Active
t5blonb35i8z4g8wf4bywkdm3     n2                  Ready               Active

# Note that the command is runnable only on manager node

Start nginx in the cluster

docker-machine ssh n1 docker service create --replicas 3 --name nginxes -p 80:80 nginx

# Or

eval `docker-machine env n1`
docker service create --replicas 3 --name nginxes -p 80:80 nginx

# *Thankfully*, even though the number of replicas is 2, all nodes can return :80 service, so that we don't have to think which node will run the tasks.

List running services

docker service ls

Update running services

docker service update --publish-rm 80:80 nginxes
# It removes published ports 80

docker service update --publish-add 80:80 nginxes
# It exports 80 again

docker service update --args "ping docker.com" helloworld
# You can even update args you passed on startup

Redisのおぼえがき

Tiny memo for my personal use of Redis. Be careful it's optimized only for me so the format probably doesn't make sense to you.

About persistence

Redis provides 2 types of persistence setting: RDB and AOF.

  • RDB:
    • Redis Database File. Stored and compressed once in a while; it can loose some data after persistence and before unexpected shutdown.
  • AOF:
    • Append Only File. A file includes all info of appending operation. A file size and startup time will be big; it almost never loose data.
    • Set appendonly to yes in redis.conf

Default Setting

https://raw.githubusercontent.com/antirez/redis/4.0/redis.conf

Use in Docker

  • Port
    • 6379
  • Data file will be:
    • /data in a container
  • Config file
    • We have to specify when to boot
docker run -it --name redis \
    -p 6379:6379 \
    -v "$PWD"/data:/data \
    -v "$PWD"/redis.conf:/usr/local/etc/redis/redis.conf \
    redis redis-server /usr/local/etc/redis/redis.conf

From https://hub.docker.com/_/redis/

Commands

Command reference – Redis

String

SET, GET

List

  • LPUSH ... Insert value from left side
  • RPUSH .. Insert from right side
  • LPOP
  • RPOP
  • LLEN ... Get length
  • LRANGE key_of_list from_index to_index # Specify -1 as to_index to get to the end

Set

  • SADD
  • SCARD ... Get length
  • SMEMBERS key ... Get all

Sorted Set

  • ZADD key_of_sorted_set score value ... The score will be a key of being sorted
  • ZRANK key value ... Returns an index (ranking order)

Hash

  • HSET user:pig name "pig"
  • HSET user:pig email "pig@gmail.com" ... Now the "user:pig" contains a hash
  • HGET user:pig name
  • HGETALL user:pig

Travis CI で WebdriverIO + Headless Google Chrome で E2E テストを通す

後述の参考の記事を組み合わせただけの簡単なお仕事。

.travis.yml

---
sudo: required
dist: trusty

addons:
  apt:
    sources:
      - google-chrome
    packages:
      - google-chrome-stable

language: node_js

node_js:
  - "7"

cache:
  directories:
    - node_modules
    - "$HOME/.npm"
    - "$HOME/.cache"

before_script:
  - "export DISPLAY=:99.0"
  - "sh -e /etc/init.d/xvfb start"
  - "npm start &"
  - "sleep 3"

wdio.conf.js 該当部分

  capabilities: [{
    browserName: 'chrome',
    chromeOptions: {
      args: ['--headless', '--disable-gpu', '--window-size=1280,800'],
    }
  }],

実際のプロジェクト

GitHub - piglovesyou/react-server-side-rendering-with-css-modules

余談

Headless Chrome はバージョン59 から。手元の Mac でも npm test コマンドでテストを実行できてる。--headlessだけで起動して、オーバーヘッドがないぶん実行も速い、手軽すぎ。

あと.travis-ci.yml の cache を知らなかった。速くて嬉しい。

参考にした記事

Arch LinuxをUSBからインストールほか

安い中古PCを何台か買って、LANに繋いで遊んでみた。コモディティマシンで分散で何か。Intel Core2Duo が1800円で買えたので(送料1500円)いつもどおり Arch Linux を入れる。もちろん問題が起きる。メモをする。

USBフラッシュメモリをインストールメディアに使う

いつもはDVDだったのだけど、買ったマシンはDVDドライブが使えない。USBにarchlinux-*.iso を書き込んで、起動時に使う。

BIOSでブートデバイスの順番を変更。中古PCとか始めててドキドキだったけど、BIOSちゃんと動いてよかった。そういえばHDDで起動したとき「This HDD was erased」とかばーんってモニタに出たけど、これどうやって出してるんだろう?消されたこと、何で覚えてるんだろう。

初め Mac OSdd したら失敗、「Isolinux.bin missing or corrupt」とか言われMacをやめて別の動いてる Arch Linuxdd したらすぐに動いた。リンク先のとおり、うまく行くマシンと行かないマシンがある、という同じ結論。

というか手元のLinuxから挿してるUSBが見れない

lsblk は物理ディスクの一覧を出すコマンドだが、USBを挿してもそれらしい物が出てこない。dmesg -w して抜き挿しすると、反応がある。

この [SOLVED] Unable to mount USB, not showing up in lsblk / Newbie Corner / Arch Linux Forums は「もしかして最近 pacman -Syu したままrebootしてないとか?」「あーそれだわ」ってあって、同じ結論だった。再起動したら lsblk にちゃんと出てきた。

isoを書き込む

推奨方法の dd bs=4M if=/path/to/archlinux.iso of=/dev/sdx && sync とほぼ同じに書き込む。やる前に bs オプションについてちょっと調べ、一度に読み書きするバッファの量だそう。試しに bs=256M とかやっても動いた。それで俺が得をしたのかどうかは調べてない。

起動

電源投入、USBが起動デバイスとして認識され、Arch Linux ってちゃんと出てくる。ほっ。

ネットワークインターフェースデバイスが出てこない、LANケーブルでネットできない

俺は Network Interface Card が壊れた中古マシンをつかまされたのか?無保証って書いてあったぞ?これが中古クオリティなのか?部品とかそいうのも買わないとなのか、俺箱の中身まで面倒見るの超面倒だぞ?どうする?

この最後の彼が言う通り rmmod tg3 ; modprobe broadcom ; modprobe tg3 でモジュールをロードし直すと解決した。lspciを見ると tg3 だけっぽいのに・・。

$ lspci
(...)
01:00.0 Ethernet controller: Broadcom Limited NetXtreme BCM57766 Gigabit Ethernet PCIe (rev 01)
        Subsystem: Broadcom Limited NetXtreme BCM57766 Gigabit Ethernet PCIe
        Flags: bus master, fast devsel, latency 0, IRQ 16
        Memory at a0400000 (64-bit, prefetchable) [size=64K]
        Memory at a0410000 (64-bit, prefetchable) [size=64K]
        Capabilities: <access denied>
        Kernel driver in use: tg3
        Kernel modules: tg3
(...)

あとはいつも通り

SWAPパーティションは必要なのかな?といつも思ってたんだが、RAMが1GBより少ない人に推奨、他は自由 とあったので今回は無しにしてみる。bootとrootだけ。

こんどGistに、シェルスクリプトのfdiskとかpacstrapとか全部やってくれる君を書こう。インストールメディアでネットに繋がった時点で落として実行。こうして人はAnsibleを学ぶ機会を逃すんだね。

というわけで

またも全ての問題はarchlinuxドメインに解決策が載っていたのだった。平和は保たれた、めでたし。

Elixirプロセス基礎

Processes - Elixir

  • OTPの軽量プロセスはLinuxのプロセスとは違う、数百が同時に稼働するのも普通
  • プロセス同士の通信は sendreceive で行われる send すると、対象のプロセスの"Mailbox"にメッセージが蓄えられる matchするとメッセージが消化される
  • 例外が起きると、そのプロセスが死ぬだけ。デフォルトでは他のプロセスに影響を与えない エラーを伝搬させたい時は明示的にLinkさせる必要がある。 プロセスに問題が起きたら死なせ、Supervisorにハンドルさせるのがパターン

DHCPのLAN内で固定IPにする2つの方法

の覚書

クライアント側で設定する場合

クライアント側のインターフェースでDHCPでなく特定のIPを持つように設定する。サブネットマスク(255.255.255.0 や /24 など)、ゲートウェイDNSIPアドレスが必要になる。

サーバへの作業が不要で楽だが、LAN内でIPが重複すると問題なので結局LAN内で足並みを合わせる必要がある。Aさんは172.168.0.200、Bさんは・・とか。

サーバ側で設定

ルーター or dhcpdが動いているサーバに、MACアドレス指定でIPを指定する。あとはクライアント側でDHCPでIPを引くと、指定した通りのものになるので楽。

インターフェースごとのMACアドレスは変わることもあるので、OSの設定で変化しないようにする。Arch Linux の systemd-networkd ではデフォルトでそうなってる。 /usr/lib/systemd/network/99-default.linkMAC アドレスを固定にしてる。普通そうなってると思う systemd-networkd - ArchWiki

Linux DHCP サーバでの設定 http://www.atmarkit.co.jp/flinux/rensai/linuxtips/944dhcpfixedip.html

Air Mac の場合はGUIから f:id:piglovesyou:20170104105338p:plain

systemd-networkd + wpa_supplicant でワイヤレスネットワーク接続

netctl で繋いでいたが、別のマシンで systemd-networkd での接続が比較的スムーズに行ったので、母艦の ArchLinux も systemd-networkd で管理することにした。netctl で接続したときはツールがいろいろ出てきて(wifi-menu, wpa_supplicant)、正直どうやって繋がっているのか分かっておらず、接続が切れたときにパニックに陥りすぐ復旧できなかったというのも systemd-networkd に揃える目的の一つ。

基本的に systemd-networkd - ArchWiki に従って進めることでうまくいった。

2010年くらいの Mac miniパーティションを切って Arch Linux を入れている。Wi-Fi インターフェース(手元だと wlp2s0b1)は認識されているのが前提。

$ ip link
...
2: wlp2s0b1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
...

まず netctl 時代に作った設定ファイルを消す。systemd-networkd が netctl で作った設定ファイルを使うことも可能のようだが、前述の理由と、Arch Wiki にある方法が最小設定だろうということで、wpa_supplicant に置き換えていく。以下で全部だったと思うが確証はなく、実際は find /etc/systemd/ してネットワーク接続に関係しそうなサービスを全て消していった。

# rm /etc/netctl/wlp2s0*
# systemctl disable netctl-auto@wlp2s0
# systemctl disable 'netctl@wlp2s0b1\x2dSSID.service'

再起動してネットに繋がらないことを確認。次に WPA supplicant - ArchWiki に沿って Wi-Fi 接続設定ファイルを作る。

# cat /etc/wpa_supplicant/wpa_supplicant-wlp2s0b1.conf
ctrl_interface=/run/wpa_supplicant
update_config=1

update_config=1 を追加すると wpa_cli による example.conf への変更が保存されるようになります。

とのこと。このあと wpa_supplicant-wlp2s0b1.conf に Wi-Fi SSID とパスコードが保存される。

# wpa_cli

ここでやることは Wiki にある内容とほぼ同じだったので割愛する。こちらを参照のこと。

WPA supplicant - ArchWiki

しかし私の場合初めに list_networks するとこれから繋ぐ SSID が登録されてあった。netctl も中で同じことをしていたのだろうか? 全て消し、 add_network set_network 0 ssid "MYSSID" set_network 0 psk "passphrase" enable_network 0 しなおした。save_config すると先ほどの wpa_supplicant-wlp2s0b1.conf に保存される。続いて起動時に接続を確立するようサービスを設定。

# systemctl start wpa_supplicant@wlp2s0b1.service
# systemctl enable wpa_supplicant@wlp2s0b1.service

Wi-Fi が利用できる状態になったところで、systemd-networkd がそれを利用しネット接続するための設定をする。Match さえすればファイル名はなんでも良いよう。

$ cat /etc/systemd/network/wlp2s0b1.network
[Match]
Name=wlp2s0b1

[Network]
DHCP=ipv4

全てのオプションは man systemd.network で見られる。

私の場合は再起動が必要だった。ネットに繋がれば成功。