25
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Dockerの中でPlay Frameworkのプロジェクトをビルドしてzipを取り出す

Last updated at Posted at 2015-09-04

sbtが取得するjarをキャッシュさせる部分で頭を捻らないといけなくて、ベストプラクティスが無い状態だけど、やってみたら意外と簡単だった。

以下の内容はCIサーバーで動かす用途を想定していて、手元のマシンで動かすことは考えてない。

Dockerfileをプロジェクトのルートに置く。

FROM java:8-jdk
COPY . /myapp
WORKDIR /myapp

Dockerfileではファイルのコピーだけやって、ビルドスクリプトでビルドする。

ビルドスクリプトはこんな感じ。

#!/bin/bash -eux

CONTAINER=myapp-build
IMAGE=myapp-build

docker build -t $CONTAINER .

# キャッシュするディレクトリをあらかじめ作っておく
mkdir -p $PWD/.ivy2 $PWD/.sbt

# 既に同名のイメージがあるとエラーになるので消しておく
docker rm $IMAGE || true

# キャッシュを使いつつビルド

docker run --name=$IMAGE -v $PWD/.ivy2:/root/.ivy2 -v $PWD/.sbt:/root/.sbt $CONTAINER ./activator dist

# イメージからzipを抜き出す
docker cp $IMAGE:/myapp/target/universal/myapp-1.0-SNAPSHOT.zip ./

# イメージを削除
docker rm $IMAGE || true

これだけで myapp-1.0-SNAPSHOT.zip が手に入る。

$PWD/.ivy2$PWD/.sbt はDockerfileで COPY . /myapp したときにコピーされると困るので .dockerignore に追加すると良い。

ついでにテストも走らせる

テストにMySQLとmemcachedを使いたかったのでDockerfileでインストール。

FROM java:8-jdk

# MySQLのインストールにrootパスワード入力を求めない
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update && apt-get install -y mysql-server memcached --no-install-recommends && rm -rf /var/lib/apt/lists/*

COPY . /myapp
WORKDIR /myapp

ビルドスクリプトの ./activator dist のところを

bash -c 'service memcached start && service mysql start && mysql -uroot < ./init.sql && ./activator test dist'

に変更。init.sqlにはデータベース作成とかユーザー作成が書いてある。

ついでにデプロイ用Dockerコンテナも作る

ビルドにはJDKが必要だけどデプロイ用にはJREだけでいい。なので上のとは別にDockerfileを作った。

Dockerfile-release

FROM java:8-jre

EXPOSE 9000

# tgzをADDすると展開されてディレクトリになる
ADD ./myapp-1.0-SNAPSHOT.tgz /

WORKDIR /myapp-1.0-SNAPSHOT
RUN ["chown", "-R", "daemon", "."]
USER daemon
ENTRYPOINT ["bin/myapp"]

zipじゃなくてtgzで出力するために、ビルドスクリプトの activator dist のところを activator universal:packageZipTarball に変更しなければいけない。

1.0-SNAPSHOTって付くのがキモい場合はbuild.sbtに name in Universal := moduleName.value と書けば myapp.tgz という名前になってくれて嬉しい。

最終的なビルドスクリプト

上に書いた要素をすべて盛り込むとこういう感じになる。

#!/bin/bash -eux

CONTAINER=myapp-build
IMAGE=myapp-build

docker build -t $CONTAINER .

# キャッシュするディレクトリをあらかじめ作っておく
mkdir -p $PWD/.ivy2 $PWD/.sbt

# 既に同名のイメージがあるとエラーになるので消しておく
docker rm $IMAGE || true

# キャッシュを使いつつテストしてからビルド

docker run --name=$IMAGE -v $PWD/.ivy2:/root/.ivy2 -v $PWD/.sbt:/root/.sbt $CONTAINER \
  bash -c 'service memcached start && service mysql start && mysql -uroot < ./init.sql && ./activator test universal:packageZipTarball'

# イメージからtgzを抜き出す
docker cp $IMAGE:/myapp/target/universal/myapp.tgz ./

# イメージを削除
docker rm $IMAGE || true

# デプロイ用コンテナを作成
docker build -t quay.io/example/myapp -f Dockerfile-release .

# quay.ioにpushする
docker push quay.io/example/myapp
25
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?