swift 2.2 in docker on Linux
今日もDockerです。最近はまってます。
今回はdockerでswift 2.2の環境をLinux上で整えます。みんなもきっとserver-side swiftとかしたいよね!
はじめに
Appleの公約どおりswiftがOSSで公開されました。
swift.org
Linuxでも動かせますがUbuntuを想定しているようです。Dockerであればディストリビューションに依らず開発・実行もできますし、swiftのバージョンごとに環境を作っておくこともできます。便利ですね。
前準備
Dockerfile
そのまま貼っておきます。大した内容ではありません。
なお、一部ファイルのread権限が不足してるためchmod -R +r /usr/lib/swiftを実行してます。
Dockerfile
FROM ubuntu:15.10 LABEL Description="swift compile environment" RUN apt-get update && apt-get install -y wget clang libicu-dev libpython2.7-dev libxml2 ENV SWIFT_VERSION swift-2.2-SNAPSHOT-2015-12-22-a ENV SWIFT_PLATFORM ${SWIFT_VERSION}-ubuntu15.10 ENV SIWFT_URL https://swift.org/builds/ubuntu1510/${SWIFT_VERSION}/${SWIFT_PLATFORM}.tar.gz RUN wget -q ${SIWFT_URL} ${SIWFT_URL}.sig RUN gpg --keyserver hkp://pool.sks-keyservers.net \ --recv-keys \ '7463 A81A 4B2E EA1B 551F FBCF D441 C977 412B 37AD' \ '1BE1 E29A 084C B305 F397 D62A 9F59 7F4D 21A5 6D5F' RUN gpg --verify ${SWIFT_PLATFORM}.tar.gz.sig && tar xzf ${SWIFT_PLATFORM}.tar.gz RUN cp -pr ${SWIFT_PLATFORM}/* / && rm -rf ${SWIFT_PLATFORM}* && \ chmod -R +r /usr/lib/swift RUN mkdir /project WORKDIR /project
swift実行ヘルパー
dockerコンテナ上で実行できるけど、毎回docker runするとstoppedコンテナで溢れかえるし、docker execもなんだか煩わしい。
そこで、ヘルパースクリプトを用意しました。
追記:docker run --rmのことを忘れていた。。。まぁいいや。
コンテナがない場合は作成してから、与えられた引数でdocker execを起動してくれます。もしコンテナがstopしていてもstartしてくれますので、要はコンテナの状態管理は気にしなくていいです。
container-exec
#!/bin/sh CID_FILE=.cid function container_not_exist() { if docker inspect `cat $CID_FILE` > /dev/null; then return 1 fi return 0 } function docker_run() { docker run -d -ti -u=`id -u`:`id -g` --cidfile=\"$CID_FILE\" -v `pwd`:/project swift:2.2 bash } if [ $# -lt 1 ]; then echo Usage: $0 command ... exit 0 fi if [ ! -e $CID_FILE ]; then docker_run elif container_not_exist; then rm -f $CID_FILE docker_run fi CID=`cat $CID_FILE` RUNNING=`docker inspect --format="{{ .State.Running }}" $CID` if [ $RUNNING = 'false' ]; then docker restart $CID fi docker exec -ti $CID $@
Dockerイメージ作成
上述のDockerfileとcontainer-execを用意しておく。
$ ls Dockerfile container-exec* $ docker build -t swift:2.2 ./ ...(略 $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE swift 2.2 b44d46edd478 3 hours ago 1.337 GB ubuntu 15.10 2804d41e7f10 2 weeks ago 133.5 MB
REPL
まずはREPLから起動してみましょう。
$ ./container-exec swift Welcome to Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 17fe37d715). Type :help for assistance. 1> 1+1 $R0: Int = 2 2> var foo = "foo" foo: String = "foo" 3> var bar = "bar" bar: String = "bar" 4> foo + bar $R1: String = "foobar" 5> import Foundation 6> import Glibc 7> srandom(UInt32(NSDate().timeIntervalSince1970)) 8> random() $R2: Int = 684624134 9> random() $R3: Int = 379490731 10> random() $R4: Int = 522347634 11>
実行ファイル作成
実行ファイルをビルドしてみましょう。
$ mkdir sources $ cat <<EOF > sources/main.swift import Foundation print("Hello, world!") EOF $ cat <<EOF > Package.swift import PackageDescription let package = Package( name: "HelloWorld" ) EOF $ ./container-exec swift build Compiling Swift Module 'HelloWorld' (1 sources) Linking Executable: .build/debug/HelloWorld $ ./container-exec .build/debug/HelloWorld Hello, world! $
以上!!!
Pulseaudio in docker
CentOS7 上でdockerを使ってpulseaudioを起動してみた。
環境
Centos7 でdockerとdocker-composeをインストールしておく。alsa関連もインストールされてることを確認。
$ yum list installed | grep alsa alsa-firmware.noarch 1.0.28-2.el7 @anaconda alsa-lib.x86_64 1.0.28-2.el7 @anaconda alsa-plugins-pulseaudio.x86_64 1.0.27-3.el7 @base alsa-tools-firmware.x86_64 1.0.28-2.el7 @base alsa-utils.x86_64 1.0.28-4.el7 @base
今回の環境のサウンドカードはこちら。
$ cat /proc/asound/cards 0 [HDMI ]: HDA-Intel - HDA Intel HDMI HDA Intel HDMI at 0xf7234000 irq 54 1 [PCH ]: HDA-Intel - HDA Intel PCH HDA Intel PCH at 0xf7230000 irq 53
PCHで音がなることを確認。
# cat <<EOF > ~/.asoundrc pcm.!default { type hw card 1 } ctl.!default { type hw card 1 } EOF # play sample.wav
docker
とくに解説はなし。
$ mkdir -p docker/pulseaudio $ cd docker $ $ cat <<EOF > pulseaudio/Dockerfile FROM centos:7 RUN yum -y install \ alsa-utils \ pulseaudio \ pulseaudio-libs \ pulseaudio-utils RUN useradd pulseaudio RUN usermod -aG audio,pulse,pulse-access pulseaudio USER pulseaudio ENTRYPOINT [ "pulseaudio" ] CMD [ "--log-level=4", "--log-target=stderr", "-v" ] EOF $ $ cat <<EOF > pulseaudio/asound.conf pcm.!default { type hw card 1 } ctl.!default { type hw card 1 } EOF $ $ cat <<EOF > pulseaudio/clinet.conf autospawn = no daemon-binary = /bin/true EOF $ $ cat <<EOF > pulseaudio/daemon.conf exit-idle-time = -1 flat-volumes = yes EOF $ $ cat <<EOF > pulseaudio/default.pa # Replace the *entire* content of this file with these few lines and # read the comments .fail # Set tsched=0 here if you experience glitchy playback. This will # revert back to interrupt-based scheduling and should fix it. # # Replace the device= part if you want pulse to use a specific device # such as "dmix" and "dsnoop" so it doesn't lock an hw: device. # INPUT/RECORD load-module module-alsa-source device="default" tsched=1 # OUTPUT/PLAYBACK load-module module-alsa-sink device="default" tsched=1 # Accept clients -- very important load-module module-native-protocol-unix load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/24;10.0.0.0/8;172.0.0.0/8 auth-anonymous=1 .nofail .ifexists module-x11-publish.so # Publish to X11 so the clients know how to connect to Pulse. Will # clear itself on unload. load-module module-x11-publish .endif EOF $ $ cat <<EOF > docker-compose.yml pulseaudio: build: pulseaudio container_name: pulseaudio command: pulseaudio -vvv --log-target=stderr volumes: - /etc/localtime:/etc/localtime:ro - /var/run/dbus:/var/run/dbus - /etc/machine-id:/etc/machine-id:ro - ./pulseaudio/asound.conf:/etc/asound.conf - ./pulseaudio/default.pa:/etc/pulse/default.pa - ./pulseaudio/client.conf:/etc/pulse/client.conf - ./pulseaudio/daemon.conf:/etc/pulse/daemon.conf ports: - "4713:4713" devices: - /dev/snd:/dev/snd environment: - HOME:/home/pulseaudio working_dir: /home/pulseaudio EOF
docker起動
$ docker-compose up -d pulseaudio
鳴らす
pulseaudio経由で音がなることを確認。
# su - # yum install pulseaudio-utils # exit $ paplay -v -s localhost sample.wav
Netlink
ifconfigよりipコマンドやssコマンドが推奨されているけど、単に置き換えるだけでなく、そもそもkernelとのやりとりがioctlからnetlink推奨に変わったという背景があるみたい。知らなかった。
d.hatena.ne.jp
とは言え、ツールの実装は全く枯れてなくてこんな話もある。
d.hatena.ne.jp
近年はsystemdやらipコマンド群やらLinux系ディストリビューション付属のツール群が大きく変わってきてるわけで、古いけど安定みたいな利点が薄れてるのかなぁ。もちろん、より管理しやすくなってる面もある。
カーネル開発のコントリビュータも増えてることからOSS開発者の母数も増えてるんじゃなかろうか。それゆえOSS開発スピードやプロジェクト数も増えてるんだろうけど、質や安定性、違いのあまりない選択肢の増加などが、OSS界隈が混沌としてきてる要因だろうとも思える。
jp.linux.com
閑話休題。
netlinkはsocketベースのインターフェースなので、unix domain socketを用いるのとあまり大差ない。netlink socketはnl_pidで区別する。netlink socketを利用するプロセスのプロセスIDと同値を用いることが推奨されるが、別に強制ではない。そもそもプロセスが複数のnetlink socketを持てば足りないし。
ユーザ空間のみでIPCとしてnetlinkを利用するなら、IPソケットと互換なunix domain socketでいいんじゃないかな。
Mac OSX with Sambaの安定化
(追記) Sierraでやり方変わりました。
macOS Sierra - Samba安定化 - Pseudo Engineer
結論から言うと、SMB1で接続するのが一番安定する。
ことの発端
自鯖のNFSは不安定でいっそQnapのNASを購入したら、なかなかというか、かなりいい感じ。Samba/NFS/AFP対応とのことで、AFPも試してみたがうまく認証が通らず使えない。なのでSamba Onlyに使っているのだが、OSXのFinderからアクセスするとやたら遅い。そこでなんとかならんもんか試行錯誤することにした。
SMBのバージョンを上げてみる
当初はSMB2で接続されていたのでQnapの設定を変えて、SMB3.0も有効にした。接続できるけどやはりFinderからは重い。なお接続したときのプロトコルバージョンはこれで確認できる。
$ smbutil statshares -a
QnapのSamba設定をいじくってみる
直接SSHでログインしてsmb.conf変えるのは危険かもしれないが仕方ない。以下を参考に直接smb.confに設定を追加し、sambaをrestartするも特に変化なし。そもそもQTS 4.1付属のSambaは4.0.3くらいだったからちょっと古いかも。
hvc-001.com
SMB1にバージョンダウン
接続をSMB1にダウンすると安定するみたい。実際やってみたら全然マシになった。
10.9: Switch the SMB stack to use SMB1 as default - Mac OS X Hints
現時点ではどうしようもない
みんな不満なのです。
www.reddit.com
Terminalからは快適
Terminalから掘っていく分にはSMBのヴァージョンに関わらず全く問題ない。Finderの挙動的がやはり問題なのだろう。フリーのいい感じのファイラーも探したが微妙ですね。じゃあ作るか(ぇ
Docker 仕組みメモ
今更感あるけどDockerの基礎技術について調べたことを自分用にメモdocs.docker.com
Dockerとは
Linux Containerによる仮想実行環境(コンテナ)を操作するツール。コンテナはホストOSから独立した環境で動作しているように見えるが、実際はホストOS上のプロセスに過ぎない。Linux Containerは割と古く2008年頃から開発している。でもVersion 1.0が提供されたのは最近で2014年。Linux ContainerはカーネルのNamespaceとcgroupsに依存している。
Namespaceは以下のようなリソースの参照を、プロセスをグループ化して隔離する機能。
Namespace Constant Isolates IPC CLONE_NEWIPC System V IPC, POSIX message queues Network CLONE_NEWNET Network devices, stacks, ports, etc. Mount CLONE_NEWNS Mount points PID CLONE_NEWPID Process IDs User CLONE_NEWUSER User and group IDs UTS CLONE_NEWUTS Hostname and NIS domain name
cgroupsは以下のようなリソースの利用を、プロセスをグループ化して制限できる機能。
CPU(使用率、割り当てコア、niceなど)、メモリ、Swap、物理IO帯域、ネットワークIO帯域、etc
コンテナの作成や実行だけならDockerがなくてもLXCでできる。しかしイメージ(コンテナのディスクイメージ)の作成やそのバージョン管理、またコンテナをexportとして他の環境へデプロイなどはDockerが得意とするところ。さらにDocker Hubを通じてイメージをインターネットで共有できる。
Dockerコンテナ
DockerコンテナはDockerイメージから作成された実行単位。start、stop、pauseもできるし、stopしたからと言ってコンテナ内で作成されたファイルが消えるわけではない。
Dockerイメージ
Dockerコンテナを作成するためのテンプレート。要はベースとなるディスクイメージ。実体はunion filesystemによる差分管理。初期のDockerはAUFSが利用されていた。今はdevice-mapperやbtrfs、overlayfsなんかが主に利用されている。なお、device-mapper(のdm-thin)はファイルシステムではなく、ブロックレベルでのoverlayを実現している。
https://www.kernel.org/doc/Documentation/device-mapper/thin-provisioning.txt
差分のbaseは空っぽのディスクイメージ。なのでDockerイメージはすべてsnapshot。
CentOS7のデフォルトはdevice-mapper。ローカルのファイル(/var/lib/docker/devicemapper/devicemapper)をループバックデバイスとしてマウントし、さらにthin provisioningでプールを構築して、イメージの差分保存に利用している。
補足:
device-mapperとは論理ブロックデバイスの中の各ブロックが、どの物理ブロックデバイス内の、どのブロックを指すかマッピングする機能。まさにメモリのページング(仮想メモリアドレスと実メモリアドレスのマッピング)のブロックデバイス版。これにより、例えばHDDとSSDを1つの大きなディスクに見せることもできる。
※実際は論理ブロックデバイス上のブロックが、さらに別の論理ブロックデバイス上のブロックを指すこともできる
docker-compose からは run じゃなくて up
docker-compose から run したあと、stopできずに悩んだ。
$ docker-compose run -d mosquitto $ docker-compose stop mosquitto # ← エラー出さないので受け付けてるようにみえる $ docker-compose ps Name Command State Ports -------------------------------------------------------------------------- mosquitto_mosquitto_run_1 /usr/sbin/mosquitto -c /et ... Up $ # 止まってない。。。
この場合、docker ps -a でコンテナID調べて直接stopさせるしかない?
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES accb9df6017d mosquitto_mosquitto "/usr/sbin/mosquitto " 2 minutes ago Up 2 minutes mosquitto_mosquitto_run_1 $ docker stop accb9df6017d accb9df6017d $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES accb9df6017d mosquitto_mosquitto "/usr/sbin/mosquitto " 3 minutes ago Exited (0) 11 seconds ago mosquitto_mosquitto_run_1
docker-compose up で起動するのが正解。
$ docker-compose up -d Starting mosquitto_mosquitto_1 $ docker-compose ps Name Command State Ports --------------------------------------------------------------------------------------- mosquitto_mosquitto_1 /usr/sbin/mosquitto -c /et ... Up 0.0.0.0:1883->1883/tcp $ docker-compose stop Stopping mosquitto_mosquitto_1 ... done $ docker-compose ps Name Command State Ports ----------------------------------------------------------------------- mosquitto_mosquitto_1 /usr/sbin/mosquitto -c /et ... Exit 0
CentOS 7 - teaming と bonding
nmtuiを触っていたらteamとbondの設定があった。Windowsではチーミング、Linuxだとボンディングと呼ばれているだけに、何で両方あるのかと思ったら、teamはbondに変わる新しい実装らしい。
詳しくはこちら。
Chapter 5. Configure Network Teaming
APIが用意されているため、teamdなど、ユーザー空間から制御できたり、機能的にもbondよりいいみたいだけど詳しくはまだ見てない。