IBM Bluemix   Swift

SwiftのWebフレームワーク「Kitura」をDockerで開発

昨日(2/23)にIBMからKituraというSwiftのWebフレームワークが公開されました。
早速、Githubの説明にそって試してみました。

Mac OSXでの環境を整える

依存ライブラリをHomebrewでインストールします。

$ brew install http-parser pcre2 curl hiredis

次に、Swiftの最新ビルドをインストールします。
swiftenvでもいけるかは不明?誰か試してください。

pkgをダウンロードしてインストールが完了したら、バイナリのある場所をPATHに通しておきます。

# bash
$ echo "export PATH=/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin:$PATH" >> ~/.bashrc
# fish
$ echo "set -x PATH /Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin $PATH" >> ~/.config/fish/config.fish

Githubの説明には、リポジトリをcloneしてswift buildとか書いてありますが、これはサンプルを実行するためのものなので省略。

プロジェクトを作ってみる

最新のswiftには、Swift Package Managerなるものが入ってるそうで、このKituraもこれを利用してかなり楽にライブラリの取り込みができます。

まず、プロジェクトのディレクトリを作ります。

$ mkdir myproject
$ cd myproject

Swift Package Managerでひな形を生成します。

$ swift build --init

すると、以下のようなツリーができます。

myproject
├── Package.swift
├── Sources
│   └── main.swift
└── Tests
    └── (空っぽ)

この、Package.swiftというのがパッケージの依存情報などを記述するもので、RubyのGemfileとかnpmのpackage.jsonとか、みたいなやつです。

これを、今回は以下のように書き換えます。

import PackageDescription

let package = Package(
    name: "myproject",

    dependencies: [
        .Package(url: "https://github.com/IBM-Swift/Kitura-router.git", majorVersion: 0),
    ]
)

次に、dependenciesに定義したパッケージをダウンロードします。

$ swift build

リンカエラーが出ますが、これは問題ないとのことです(Swift Package ManagerはC言語をコンパイルしないために起きるそうです)。

次に、Makefileをパッケージ内のファイルからコピーしてきます。

$ cp Packages/Kitura-net-0.2.0/Makefile-client Makefile

ソースファイル(Sources/main.swift)を書き換えます。

import KituraRouter
import KituraNet
import KituraSys

let router = Router()

router.get("/") {
    request, response, next in

    response.status(HttpStatusCode.OK).send("Hello, World!")

    next()
}

let server = HttpServer.listen(8090, delegate: router)
Server.run()

ここまできたら、最後にmakeします。

$ make

さっきのようなエラーは出ないはずです。無事にビルドできたら、実行してみます。

$ .build/debug/myproject &
$ curl -l http://localhost:8090/
Hello, World!
$ kill %1

Dockerで動かす

Webアプリケーションなので、Dockerコンテナを作ってそこで動かしたいですね!
ということで、Dockerfileを作ってみました。

FROM ubuntu:wily

MAINTAINER d-abe <abe@flup.jp>

ENV PATH /opt/swift/usr/bin:$PATH
ENV LD_LIBRARY_PATH /usr/local/lib:$LD_LIBRARY_PATH

RUN apt-get update \
    && apt-get install -q -y git wget clang dh-autoreconf pkg-config libkqueue0 libkqueue-dev libbsd-dev libblocksruntime-dev libicu-dev build-essential libhttp-parser-dev libcurl4-openssl-dev libhiredis-dev \
    && rm -rf /var/lib/apt/lists/* \
    && wget https://swift.org/builds/development/ubuntu1510/swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a/swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a-ubuntu15.10.tar.gz \
    && tar zxf swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a-ubuntu15.10.tar.gz \
    && mkdir -p /opt/swift \
    && mv swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a-ubuntu15.10/usr/ /opt/swift/ \
    && git clone -b opaque-pointer git://github.com/seabaylea/swift-corelibs-libdispatch \
    && cd swift-corelibs-libdispatch \
    && sh ./autogen.sh \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && wget https://raw.githubusercontent.com/IBM-Swift/Kitura/master/Sources/Modulemaps/module.modulemap -O /usr/local/include/dispatch/module.modulemap \
    && wget http://ftp.exim.org/pub/pcre/pcre2-10.20.tar.gz \
    && tar zxf pcre2-10.20.tar.gz \
    && cd pcre2-10.20 \
    && ./configure \
    && make \
    && make install 

WORKDIR /src

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

RUNの部分はLinux版のインストール手順をほぼそのまま書いただけです。

ENTRYPOINTのスクリプトは、作業フォルダのファイルをまとめて/workにコピーして、
そこで swift build → make → ビルドしたファイルの実行を行っています。

#!/bin/bash

set -eu

if [ -z "$PROJECT_NAME" ]; then
    echo >&2 'PROJECT_NAME is not specified!'
    exit 1
fi

mkdir /work
cp -rf * /work

cd /work

set +e
swift build
set -e

make
exec ".build/debug/${PROJECT_NAME}"

-e でPROJECT_NAMEという環境変数を渡しておかないと動作しないようになっています。

【追記】なぜわざわざコピーしている?

最初は単にVOLUMESでコンテナから直接読み込んでビルドさせようとしていたのですが、なぜかmakeに失敗(HttpParserが見つからないなどのエラー)してしまったのでコンテナ内のフォルダにソースを一式コピーしてmakeさせるように変更したという経緯があります。

Docker Compose

パラメータを渡すのが面倒なので、docker-compose.yamlも作りましょう。

kitura:
  build: ../../swift-kitura
  volumes:
    - "${ROOT_DIR}/myproject:/src"
  ports:
    - "8090:8090"
  working_dir: /src
  environment:
    PROJECT_NAME: myproject

これで、一応ローカルのファイルをDockerコンテナ上でビルドして実行できると思います。

godoみたいに監視して自動的にビルド&再起動できる仕組みも作りたいですね。
あと、Dockerで動くということはwerckerでも動かせますね!

今後が楽しみです。

参考サイト

Swift で書ける Web フレームワーク「Kitura」を触ってみた | Developers.IO

Swift WebフレームワークKituraをDocker on Amazon EC2で動かしてみた | Developers.IO

LINEで送る
Pocket

SwiftのWebフレームワーク「Kitura」をDockerで開発」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です