文字っぽいの。

文字を書いています。写真も混ざります。

サーバサイドSwift を Heroku にデプロイする with Kitura

はじめに

この記事では

  • Swift 3.0.2
  • Swift Package Manager
  • Kitura

を利用して、Heroku上で簡単なサーバを動作させる手順を記載します。

Swift PMを使ってプロジェクトをセットアップ

まずは、最新版のXcode8.2をインストールしましょう。その後はシェル上で次のコマンドを叩きます。

$ mkdir kitura-test
$ cd kitura-test
$ swift package init --type executable

これでコードを書く準備が整いました。ディレクトリ構造は次のようになっているはずです。シンプルで安心。

.
├── Package.swift
├── Sources
│   └── main.swift
└── Tests

この段階でもビルドが可能です。

$ swift build
$ ./.build/debug/kitura-test
# Hello, world!

コンソールに Hello, world! が出力されると思います。もし、コードの編集やビルドをXcodeで行いたい場合は、

$ swift package generate-xcodeproj

とすればXcodeプロジェクトが生成されます。

Kituraを導入してローカルにサーバを立てる

Package.swiftを編集して、Kituraを使えるようにします。

import PackageDescription

let package = Package(
    name: "kitura-test",
    dependencies: [
        .Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 1, minor: 4)
    ]
)

次に Sources/main.swift を編集します。

import Foundation
import Kitura

let router = Router()

router.get("/") { request, response, next in
    response.send("Hello, World!")
    next()
}

Kitura.addHTTPServer(onPort: 8090, with: router)

Kitura.run()

ここまで編集し終わったら

$ swift build
$ ./.build/debug/kitura-test

を実行しましょう。ライブラリが自動で導入され、ビルドが走ります。 ./.build/debug/kitura-test 実行時に特にログは流れてきませんが、サーバは立っているのでブラウザからlocalhost:8090にアクセスしてみましょう。Hello, World! と表示されればOKです。

Herokuにデプロイする

Herokuにデプロイする前に、PORT番号をよしなにする必要があります。まずは Sources/main.swiftを編集しましょう。

import Foundation
import Kitura

let router = Router()

router.get("/") { request, response, next in
    response.send("Hello, World!")
    next()
}

// Herokuでポート番号が変えられるようにする
let port: Int = Int(ProcessInfo.processInfo.environment["PORT"] ?? "8090") ?? 8090

Kitura.addHTTPServer(onPort: 8090, with: router)

Kitura.run()

次にProcfileを生成します

$ echo web: .build/release/kitura-test > Procfile

さて、それではHerokuにデプロイしていきましょう。

$ git init
$ git add .
$ git commit -m 'first commit'
$ heroku create your-project-name
$ heroku buildpacks:set https://github.com/kylef/heroku-buildpack-swift
$ git push heroku master # ビルドも走るのでちょっと時間かかります
$ heroku open

heroku openをするとブラウザが立ち上がります。画面にHello, World!が表示されれば勝利。サーバサイドSwiftをHerokuで動かすことができました。

補足:ログを流したい人へ

HeliumLoggerというライブラリを利用します。Package.swiftSources/main.swiftを編集します。

import PackageDescription

let package = Package(
    name: "kitura-test",
    dependencies: [
        .Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 1, minor: 4),
        .Package(url: "https://github.com/IBM-Swift/HeliumLogger.git", majorVersion: 1, minor: 4)
    ]
)
import Kitura
import Foundation
import HeliumLogger

// HeliumLoggerを初期化
HeliumLogger.use()

let router = Router()
router.get("/") { request, response, next in
    response.send("Hello, World!")
    next()
}

// Herokuでポート番号が変えられるようにする
let port: Int = Int(ProcessInfo.processInfo.environment["PORT"] ?? "8090") ?? 8090

Kitura.addHTTPServer(onPort: port, with: router)

Kitura.run()

これだけです。あとはswift buildをした後でサーバを立ち上げ、アクセスをすると

[2017-01-11T18:20:25.581+09:00] [VERBOSE] [Router.swift:67 init(mergeParameters:)] Router initialized
[2017-01-11T18:20:25.596+09:00] [VERBOSE] [Kitura.swift:70 run()] Starting Kitura framework...
[2017-01-11T18:20:25.596+09:00] [VERBOSE] [Kitura.swift:80 start()] Starting an HTTP Server on port 8090...
[2017-01-11T18:20:25.597+09:00] [INFO] [HTTPServer.swift:85 listen(on:)] Listening on port 8090
[2017-01-11T18:20:43.031+09:00] [VERBOSE] [HTTPIncomingMessage.swift:245 parsingCompleted()] HTTP request from=127.0.0.1; proto=http;

このようにログが吐かれます。便利便利。

最後に

Swift3が開発中だったころのサーバサイドSwiftは、必要で手元で動かすのも大変でしたが、今では少ないコード量で簡単に動かすことができます。

また、Xcodeを利用せずにコードの編集・ビルド・実行ができるので、EmacsVimAtomでSwiftを書きたい人でも安心です。ただし、補完機能についてはSourceKittenを使う必要があり、まだちょっと不便です。

とはいえ、普段利用しているSwiftで簡単にサーバが作れるので、JSONを返すだけの趣味サーバなどは、RubyからSwiftに移行していこうと思います。