swift 2.2 in docker on Linux

今日もDockerです。最近はまってます。
今回はdockerでswift 2.2の環境をLinux上で整えます。みんなもきっとserver-side swiftとかしたいよね!

はじめに

Appleの公約どおりswiftOSSで公開されました。
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!
$ 

以上!!!