はじめに
Server Side Swift の開発をより実践的にできればと思い、CapistranoライクなServer Side Swiftフレームワークのデプロイツールである Flock を使ってみました。
今回の投稿では Vapor で作ったプロジェクトのEC2サーバーへのデプロイを行います。
- Flock
- Capistoranoライクな Server Side Swift のフレームワークデプロイツール
- Vapor, Kitura, Zewo, Perfect に対応しているよう
- Vapor
- Server Side Swift の Webフレームワーク
手順概要
- Vaporプロジェクトの作成
- EC2でUbuntuサーバー(デプロイ先サーバー)の作成
- デプロイ先サーバーでのNginxの設定
- デプロイ先サーバーでのsupervisorの設定
- デプロイ先サーバーでのその他デプロイに必要な設定
- ローカルmacでFlockの設定
- いざ、デプロイ
環境
-
開発機
- macOS Sierra 10.12.1
- Swift 3.0.1
- Vapor 1.1.13
- Flock 0.1.1
-
デプロイ先サーバー
- Ubuntu 16.04
- Swift 3.0.1
1. Vaporプロジェクトの作成
▶︎ ローカルmacにプロジェクト作成
まずは開発用のローカルmacにVaporプロジェクトを作成します。
今回は、デプロイ部分を中心に見ていくので、VaporのインストールやVapor自体の説明は割愛します。
(詳しくはVaporのDocumentをご覧ください。)
$ vapor new vaporDeploySample
※vaporDeploySample
部分はプロジェクト名になるので、適宜変更してください。
▶︎ GithubへPush
今回は特にプロジェクトはいじらずにそのままデプロイ設定の手順に進むので、一旦GithubにPushしておきます。
GithubのリポジトリのURLを後述のデプロイ設定の際に使用します。
2. EC2でUbuntuサーバー(デプロイ先サーバー)の作成
EC2でなくても大丈夫なのですが、VagrantでUbuntu14.04
で試した時に何かと面倒があったので、EC2でUbuntu16.04
を立てて行いました。
▶︎ EC2の作成
AMIの選択
Ubuntu Server 16.04 ...
のものを選択して作成を進めていきます。
キーペア
キーペアを新しく作成する場合は、
- 作成したキーをダウンロード
- 手元のmacの
~/.ssh
の下に配置 chmod 600 ~/.ssh/your-key-pair.pem
としておきます。
セキュリティグループの設定
セキュリティ設定では、今回の作業ではSSHとHTTPが開いていれば十分です。
下の画像では送信元が「任意の場所」になっていますが、手元で試すだけなら「マイIP」を選択して自分のIPからのみアクセスできる状態にしておいた方が安心です。
3. デプロイ先サーバーでのNginxの設定
▶︎ サーバーへ接続
先ほど作成したサーバーへ接続して、作業を行います。
$ ssh -i ~/.ssh/your-key-pair.pem ubuntu@publicdns
publicdns
部分は作成したインスタンスのパブリックDNSが入ります。
▶︎ Nginxインストール
サーバーへログインできたら、Nginxをインストールします。
$ sudo apt-get update
$ sudo apt-get install nginx
▶︎ Nginxの設定
/etc/nginx/sites-enabled/default
ファイルに以下のような設定を書きます。
server {
server_name localhost;
listen 80;
try_files $uri @proxy;
location @proxy {
proxy_pass http://127.0.0.1:8080;
proxy_pass_header Server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Server;
proxy_connect_timeout 3s;
proxy_read_timeout 10s;
}
}
$ sudo service nginx restart
これで、localhostの80番ポートへのアクセスをVaporのプロジェクトがデフォルトでバインドする8080番へ流してくれます。
4. デプロイ先サーバーでのsupervisorの設定
続いて、プロセス監視のため、supervisorをインストールします。
$ sudo apt-get update
$ sudo apt-get install supervisor
こちらの設定は後述のFlockを使って行うので、まずはインストールまででokです。
(※このタイミングでインストールしていなくても、後述のflock tools
タスクの中でインストールされそうですが、試行錯誤していたので確認できていません。もし良ければお試しください。)
5. デプロイ先サーバーでのその他デプロイに必要な設定
▶︎ /var/www
ディレクトリの作成
Flockでは /var/www
ディレクトリにデプロイされるので、もしない場合は作っておきます。
(EC2ではデフォルトであるようなので、この工程は不要です。)
また、後述の設定でデプロイ先のディレクトリの変更も可能です。
$ sudo mkdir /var/www
# ↑本来はwwwユーザーとか作ってそのユーザーのみにwww以下を触らせるのが良さそうですが、一旦そのまま動かします
▶︎ rootでのログイン
あまり気が進まないですが、Flockを使っていてrootでのログインができないと困ることが多々でてきたので、rootでのログイン設定をします。
(適切なパーミッションを持ったユーザーを使ったり、Flock自体の改善でrootでのログインは回避できるかもしれませんが、一旦簡単のためにそうします。)
$ mv /root/.ssh/authorized_keys /root/.ssh/authorized_keys_bak
$ cp -f /home/ubuntu/.ssh/authorized_keys /root/.ssh/authorized_keys
authorized_keysをコピーすることで、手元のmacからキーペアを使ってrootユーザーでログインすることができます。
6. ローカルmacでFlockの設定
それでは、いよいよデプロイをする準備をしていきます。
▶︎ Flockのインストール
$ brew install jakeheis/repo/flock
▶︎ プロジェクト直下でFlockの初期化
$ cd /path/to/your/project
$ flock --init
Creating Flock files...
Creating .flock
Creating config/deploy
Writing .flock/Package.swift
Writing config/deploy/FlockDependencies.json
Writing Flockfile
Linking Flockfile to .flock/main.swift
Creating environment `always`
Writing config/deploy/Always.swift
Linking config/deploy/Always.swift to .flock/Always.swift
Creating environment `production`
Writing config/deploy/Production.swift
Linking config/deploy/Production.swift to .flock/Production.swift
Creating environment `staging`
Writing config/deploy/Staging.swift
Linking config/deploy/Staging.swift to .flock/Staging.swift
Successfully created Flock files
Downloading and building dependencies...
Successfully downloaded dependencies
Adding Flock files to .gitignore...
Successfully added Flock files to .gitignore
Successfully initialized Flock!
IN ORDER FOR FLOCK TO WORK CORRECTLY
Follow these steps:
1. Update the required fields in config/deploy/Always.swift
2. Add your production and staging servers to config/deploy/Production.swift and config/deploy/Staging.swift respectively
To add Flock dependencies:
1. Add the url and version of the dependency to config/deploy/FlockDependencies.json
2. in your Flockfile, at the top of the file import your dependency and below add `Flock.use(Dependency)`
これによって、Flockfile
というファイルとConfig/
下にdeploy
というディレクトリが作られ、deployに必要な設定を行うことができるようになります。
▶︎ Config/deploy/FlockDependencies.json
の編集
Vaporデプロイ用にVaporFlockを使うので、追記します。
以下のファイルが編集後のものです。
https://github.com/jakeheis/VaporFlock
のブロックを追加しています。
{
"dependencies" : [
{
"url" : "https://github.com/jakeheis/Flock",
"version": "0.1.1"
},
{
"url" : "https://github.com/jakeheis/VaporFlock",
"version": "0.0.4"
}
]
}
ここでの依存関係のバージョンが食い違うとエラーが起こるので、注意が必要です。
例えば、VaporFlockのversionを0.0.3とすると、VaporFlock v0.0.3 はソース上(Package.swift)では Flock v0.0.x に依存しているため、このファイルの記述と食い違いが起こります。
▶︎ Flockfile
の編集
以下が編集後のFlockfile
。
import Flock
import VaporFlock
Flock.use(Flock.Tools)
Flock.use(Flock.Deploy)
Flock.use(Flock.Vapor)
Flock.configure(.always, with: Always()) // Located at config/deploy/Always.swift
Flock.configure(.env("production"), with: Production()) // Located at config/deploy/Production.swift
Flock.configure(.env("staging"), with: Staging()) // Located at config/deploy/Staging.swift
Flock.run()
▶︎ Config/deploy/Always.swift
の編集
環境に依らない、共通の設定をこのファイルに書きます。
- Config.projectName
- Config.executableName
- Config.repoURL
- Config.swiftVersion
の値をプロジェクトに応じて変更します。
import Flock
class Always: Configuration {
func configure() {
// UPDATE THESE VALUES BEFORE USING FLOCK:
Config.projectName = "vaporDeploySample"
Config.executableName = "App" // Same as Config.projectName unless your project is divided into modules
Config.repoURL = "https://github.com/taji-taji/vaporDeploySample"
// Optional config:
// Config.deployDirectory = "/var/www"
Config.swiftVersion = "https://swift.org/builds/swift-3.0.1-release/ubuntu1510/swift-3.0.1-RELEASE/swift-3.0.1-RELEASE-ubuntu15.10.tar.gz"
}
}
Config.executableName
は、プロジェクトがビルドされて生成される実行ファイルの名前を指すようで、コメントには Same as Config.projectName unless your project is divided into modules
と書いていますが、私が行った際には実行ファイルはApp
になっていたので、そのようにしました。
フレームワークによって違うのかもしれません。
(これが分からなくてしばらくハマりました、、)
▶︎ Ubuntuサーバーに接続するsshキーを環境変数に設定
Flockのコード内からUbuntuサーバー作成時に作成したキーペアを環境変数を通して読み込むので、環境変数への設定を行います。
$ export FLOCK_KEY=$HOME/.ssh/your-key-pair.pem
Config/deploy/Production.swift
の編集
ここで、デプロイ先のIPやそこに接続するためのsshキー(先ほど設定したもの)の設定を行います。
import Flock
import Foundation
class Production: Configuration {
func configure() {
if let key = ProcessInfo.processInfo.environment["FLOCK_KEY"] {
Config.SSHAuthMethod = .key(key)
}
// using vagrant private network ip
Servers.add(ip: "ec2-ip", user: "root", roles: [.app, .db, .web])
}
}
"ec2-ip"
部分にはEC2のパブリックIPを設定します。
ProcessInfo.processInfo.environment["FLOCK_KEY"]
の部分で先ほど環境変数に設定したキーペアの場所が読まれています。
注意点
デフォルトでFoundation
フレームワークがimportされていなかったため、ProcessInfo
の使用で怒られました。
環境変数を読むときはimport Foundation
を追記しましょう。
デプロイ
▶︎ flock tools
コマンド
初回はflock tools
コマンドでデプロイ先のサーバーにSwiftと依存するライブラリをインストールします。
$ flock tools
このflock tools
コマンドでは、
- デプロイ先サーバーにデプロイに必要な依存ライブラリをインストール
- デプロイ先サーバーにswiftenvのインストールおよびswiftenvによるSwiftをインストール
という2つのフェーズに分かれており、それぞれ、
flock tools:dependencies
flock tools:swift
というコマンドで別々に実行することが可能です。
▶︎ flock deploy
コマンド
いよいよデプロイです。
$ flock deploy
こちらも
- gitからソースコードをcloneする
- コードをbuildする
- デプロイした最新のコードがあるディレクトリにリンクを貼る
というフェーズに分かれており、それぞれ下のコマンドで別々に実行できます。
flock deploy:git
flock deploy:build
flock deploy:link
補足:デプロイ先ディレクトリについて
/var/www/vaporDeploySample/
├── current -> /var/www/vaporDeploySample/releases/20161211181262
└── releases
├── 20161211181234
└── 20161211181262
Capistranoを使っている方には馴染みがあるかと思いますが、デプロイ先のディレクトリ構成には current
と releases
というディレクトリがあります。
デプロイしたコードをreleases
に貯めていき、最新のものをcurrent
にリンクするようにしています。
もしデプロイしたものに異常があってもリンクを差し替えるだけでデプロイ前の状態に戻すことが可能です。
以上でデプロイの手順は完了となります。
お疲れ様でした。
一度上記の設定を行えば、以降はflock deploy
コマンドのみでデプロイができます。
今回作成したサンプルアプリケーション
今回作成したサンプルアプリケーションです。
Vaporプロジェクトはデフォルトのテンプレートのまま、「Flockfile
」および「Config/deploy
」以下のdeploy用の設定ファイルが追加された形になります。
感想
普段、Capistranoを使っている方にとっては学習コストも低く、とても便利に使えるツールだと思います。
一方で、Server Side Swift そのものがそうであるように、このような付随するツールもまだ安定していないものが多かったりします。
なので、こういったツールへの貢献ができるようにというのが今後の自分の課題です。
Server Side でも Swift を楽しめるといいですね!
最後に
とりあえず、今回は「デプロイをする」ことのみに絞ってみましたが、これから、もう少し機能的にどんなことができるかなどを深掘りしてみたいと思います。