Created
May 11, 2016 10:16
-
-
Save joker1007/8f1ab3dce906296f6655d43e53834b00 to your computer and use it in GitHub Desktop.
capistranoでビルドサーバーにdocker buildを実行してもらう処理のサンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace :docker do | |
desc "build and push docker image on remote host" | |
task :build do | |
docker_registry_host = SSHKit::Host.new(fetch(:docker_registry_host)) | |
docker_registry_host.ssh_options = { | |
user: "ec2-user", | |
keys: ENV['SSH_KEY'], | |
} | |
sha1 = `git rev-parse #{fetch(:branch)}`.chomp | |
staging_or_release = fetch(:rails_env).to_s == "staging" || fetch(:rails_env).to_s == "production" | |
precompile_target = staging_or_release ? "all" : fetch(:rails_env) | |
without_cache = ENV["WITHOUT_CACHE"].to_s != "" | |
on docker_registry_host do | |
old_verbosity = SSHKit.config.output_verbosity | |
begin | |
SSHKit.config.output_verbosity = :debug | |
within "/home/ec2-user" do | |
# githubのリポジトリと同期する | |
execute(:if, "[ -e repo ]; then cd repo && git remote update; else git clone --mirror [email protected]:<user>/<repo>.git repo; fi") | |
end | |
within "/home/ec2-user/repo" do | |
# ビルド時に利用するキャッシュを保持するディレクトリを用意する | |
execute(:if, %Q{[ -e tmp/docker_build_cache ]; then rm -rf tmp/docker_build_cache; fi}) if without_cache | |
execute(:mkdir, "-p tmp/docker_build_cache") | |
# 同時に複数人がビルドできるようにタイムスタンプとgit worktreeを利用して作業ディレクトリを分ける | |
timestamp = Time.now.strftime("%s%L") | |
execute(:git, :worktree, :add, "./worktree-#{timestamp}", sha1) | |
begin | |
within "worktree-#{timestamp}" do | |
execute(:mkdir, "-p tmp") | |
execute(:cp, "-r", "../tmp/docker_build_cache", "tmp/docker_build_cache") | |
# 必要ならプライベートレジストリにログインする | |
# execute(:sudo, "docker login <credential> <server>") | |
# execute(:sudo, "docker pull <baseimage>") | |
SSHKit.config.output_verbosity = :info | |
with yaml_vault_passphrase: ENV["YAML_VAULT_PASSPHRASE"], yaml_vault_sign_passphrase: ENV["YAML_VAULT_SIGN_PASSPHRASE"] do | |
# dockerコンテナをビルドする | |
# この時点でassets:precompile assets:sync等を実行する | |
execute(:sudo, "docker", "build", "--force-rm", "#{without_cache ? "--no-cache" : ""}", "-t", | |
"app:#{timestamp}", | |
"--build-arg=precompile=#{precompile_target}", | |
"--build-arg=git_commit=#{sha1}", | |
"--build-arg=yaml_vault_pass=${YAML_VAULT_PASSPHRASE}", | |
"--build-arg=yaml_vault_sign_pass=${YAML_VAULT_SIGN_PASSPHRASE}", | |
".") | |
end | |
SSHKit.config.output_verbosity = :debug | |
# 作成したイメージをプッシュする | |
execute(:sudo, "docker tag -f app:#{timestamp} #{fetch(:docker_registry_host_with_port)}/app:#{sha1}") | |
execute(:sudo, "docker push #{fetch(:docker_registry_host_with_port)}/app:#{sha1}") | |
# release対象には特別にタグを付ける | |
if staging_or_release | |
execute(:sudo, "docker tag -f app:#{timestamp} #{fetch(:docker_registry_host_with_port)}/app:#{fetch(:rails_env)}") | |
execute(:sudo, "docker push #{fetch(:docker_registry_host_with_port)}/app:#{fetch(:rails_env)}") | |
end | |
# dockerコンテナ内でassets:precompileした結果のキャッシュを抽出し保管しておく | |
# 次回ビルド時にコンテナ内にADDすることでassets:precompileの実行時間を短縮する | |
execute(:if, %Q{[ $(sudo docker ps -aq -f name=pickup_docker_cache | grep "\w") ]; then sudo docker rm -f $(sudo docker ps -aq -f name=pickup_docker_cache); fi}) | |
execute(:sudo, "docker run -it -d --name pickup_docker_cache app:#{timestamp} shell") | |
execute(:sudo, "docker cp pickup_docker_cache:/app/tmp/cache - | gzip > ../tmp/docker_build_cache/tmp_cache.tar.gz") | |
execute(:sudo, "docker rm -f pickup_docker_cache") | |
# pushして不要になったタグを削除する | |
execute(:sudo, "docker rmi #{fetch(:docker_registry_host_with_port)}/app:#{sha1}") | |
if staging_or_release | |
execute(:sudo, "docker rmi #{fetch(:docker_registry_host_with_port)}/pp:#{fetch(:rails_env)}") | |
end | |
# ビルドサーバー上で保持しておく数の上限を越えた古いイメージを削除する | |
execute(:sudo, %Q{docker images | awk '/^app/ { print sprintf("%s:%s", $1, $2) }' | sort -r | awk 'NR > #{fetch(:keep_docker_image_count)} { print $0 }' > /tmp/app-old-images}) | |
execute("while read image_id; do sudo docker rmi ${image_id}; done < /tmp/app-old-images") | |
end | |
ensure | |
# worktreeを削除する | |
execute(:rm, "-rf", "worktree-#{timestamp}") | |
execute(:git, :worktree, :prune) | |
end | |
end | |
ensure | |
SSHKit.config.output_verbosity = old_verbosity | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment