Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Rails App Deployment with CodeDeploy
Search
tannai
August 30, 2016
Programming
1.6k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Rails App Deployment with CodeDeploy
http://classmethod.connpass.com/event/38180/
tannai
August 30, 2016
More Decks by tannai
See All by tannai
redash patche at dmm
yuukigoodman
0
780
akibago-2018-10-30
yuukigoodman
0
97
serverless-design-and-streaming-date-processing-service
yuukigoodman
0
1.1k
alexa-changes-development-process
yuukigoodman
0
1.7k
VUIとAlexaによるちょっと未来の体験の話2
yuukigoodman
0
950
regrowth2016alexa
yuukigoodman
0
1.4k
cognito-userpools-in-production
yuukigoodman
4
9k
aws-lambda-in-practice
yuukigoodman
2
2.2k
serverless-from-today
yuukigoodman
2
2.3k
Other Decks in Programming
See All in Programming
AIがコードを書いてくれる時代、我々は何を確かめるのか
yosuke_furukawa
PRO
13
5.8k
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
220
SODA - FACT BOOK(EN)
sodainc
1
220
Performance Optimization With LLMs
xleitix
0
250
느린 네트워크와 저사양 디바이스 사용자를 위한 웹뷰 로딩 시간 개선기
kmkim
1
220
Goコンパイラを作ってGoをもっと理解する / Build a Go compiler to better understand Go
ikura_hamu
0
130
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
310
Crash Auto Pipelines
veronikapj
1
400
DroidKnights 2026 Android A2UI Jetpack Compose 기반의 안전한 AI UI 렌더링 - 박제창
itsmedreamwalker
1
210
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
4
3.6k
AI時代のIaC入門 〜なぜインフラをコードで管理したいのか?〜 / Introduction to IaC in the AI Era
akihisaikeda
6
1.4k
社内AIエージェント「Askワンバン」における コストチューニングの取り組み
t0yohei
0
160
Featured
See All Featured
New Earth Scene 8
popppiees
4
2.8k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.9k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
550
Balancing Empowerment & Direction
lara
6
1.4k
WENDY [Excerpt]
tessaabrams
14
40k
Test your architecture with Archunit
thirion
2
2.5k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
370
How GitHub (no longer) Works
holman
316
150k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
580
Transcript
RailsΞϓϦΛ σϓϩΠ͢Δ CodeDeploy Classmethod, Inc. Yuki Tannai ࣮ફAWSϓϩάϥϛϯά
ࣗݾհ • ୮༏ل • @yuukigoodman • αʔόͰಈ͘ϓϩάϥϜͱ͔AWS
Agenda • σϓϩΠͱ • σϓϩΠΛࢧ͑ΔAWS • CodeDeployͰRailsΛσϓϩΠ
σϓϩΠͱ
γεςϜΛ ར༻Մೳʹ͢Δ ׆ಈશൠͰ͋Δ — ja.wikipedia.org1 1 https://ja.wikipedia.org/wiki/ιϑτΣΞσϓϩΠϝϯτ
• ͨͩίʔυΛμϯϩʔυͯ͠ىಈ͢Εྑ͍ ͱ͍͏ͷͰͳ͍ • σϓϩΠʹΑͬͯղܾ͍͕ͨ͋͠Γɺ ͦΕϓϩδΣΫτͷਐߦͱڞʹมԽ͢Δ • σϓϩΠαʔϏεఏڙऀͷΛղܾ͢Δ • ఏڙऀͷղܾར༻ऀͷՁʹͳΓಘΔ
• σϓϩΠ࣭ͷͻͱͭ(QCD) • Quality/Cost/Delivery
σϓϩΠࣗಈԽͷಈػ • ස͕ଟ͍ • ϛε͕Ͱ͖ͳ͍ • ϧʔνϯϫʔΫ • ͰʑมΘΔ ࣗಈԽ͠ͳ͍ͱͬͯΒΜͶʔʂʂ
σϓϩΠࣗಈԽͷ؍ • Ͳ͔͜ΒͲ͜ʹσϓϩΠ͢Δ͔ • ࣗಈσϓϩΠͷ࣮ߦτϦΨʔ • ͍ͭ୭͕σϓϩΠ͢Δ͔ • ࣦഊΛͲ͏ݕग़͠ɺͲ͜ʹ௨͢Δ͔ •
Ͳͷ͘Β͍มߋ͕ೖΔ͔
σϓϩΠϓϩδΣΫτͷਐߦͱͱʹมԽ͢Δ • Ϗδωε: ༷มߋೲظॖ • ৫: ϝϯόʔͷೖΕସ͑૿ݮɺख़ͷෆ ۉҰ͞ • ٕज़:
όʔδϣϯΞοϓύϑΥʔϚϯε ͜ΕΒͷཧ༝ʹΑΓσϓϩΠมߋ͞ΕΔ
มߋʹ͑͏Δ σϓϩΠࣗಈԽͷ ϓϩάϥϜΛॻ͘
ͦͷͨΊͷඪઃఆͱઃܭ͕େࣄ
σϓϩΠΛࢧ͑Δ AWS
None
EC2 • ΦʔιυοΫεͳσϓϩΠλʔήοτ • େͷ߹EC2ʹσϓϩΠ͢Δ • Πϯελϯε࡞ͱϓϩϏδϣχϯά͕ඞཁ
None
Elastic Beanstalk • HerokuΈ͍ͨͳαʔϏε • EC2/RDS/ELBϦιʔεΛ؆୯ʹཧ͢Δ • ࣮ମCFn • ઐ༻ͷίϚϯυ(eb-cli)͕͋Δ
• eb deploy
None
Cloud Formation • AWSϦιʔεͷߏཧ • ϒϥβCLIͰ͍ͬͯΔ͜ͱΛJSONͰهड़ ͢Δͱ࣮ߦͯ͘͠ΕΔ • AWSެࣜఏڙπʔϧͳͷͰ҆৺ •
࠶ݱੑ͕ٻΊΒΕΔ߹ඇৗʹ༗ޮ
None
EC2 Container Service • EC2Ϋϥελ্Ͱͷίϯςφ࣮ߦΛཧ • Dockerӡ༻ʹৄ͍͠ਓɺ ͥͻ࠙ձͰڭ͍͑ͯͩ͘͞ >< •
Container Registry౦ژʹདྷͨ
None
Code Deploy • EC2ͷίʔυͷஔͱىಈΛཧ͢ΔαʔϏε • ຊͷओਓެ • EC2ʹAgentΛΠϯετʔϧ͓ͯ͘͠
CodeDeployͰ RailsΛσϓϩΠ
େ·͔ͳྲྀΕ • Ansible Playbookͷ࡞ • CodeDeployઃఆͷ࡞ • Cloud Formation Templateͷ࡞
• σϓϩΠͯ͠ΈΔ • Ճཁ݅Λ࣮͢Δ • ࣦഊ࣌ͷ௨ • Blue Green Deployment
Ansible Playbookͷ࡞
webservers.yml - hosts: all remote_user: ec2-user vars: rails_env: "{{ lookup('env',
'RAILS_ENV') }}" roles: - common - nginx - fluentd - logrotate - ruby - node - rails - ssh
roles/common/tasks/main.yml - name: install yum security plugin yum: pkg=yum-plugin-security state=latest
sudo: yes - name: update yum security shell: yum -y --security update-minimal sudo: yes
roles/common/tasks/main.yml - name: install yum packages yum: name={{ item }}
state=present sudo: yes with_items: - gcc-c++ - glibc-headers - openssl-devel - readline - readline-devel - libyaml-devel - libffi-devel - libxml2 - libxslt - libxml2-devel - libxslt-devel - zlib - zlib-devel - mysql-devel - git - ruby-devel
roles/node/tasks/main.yml - name: install nodejs yum: name=nodejs enablerepo=epel sudo: yes
roles/ruby/tasks/main.yml - name: check rbenv presence command: which rbenv ignore_errors:
true register: rbenv_path - name: Install rbenv sudo: yes git: repo=https://github.com/sstephenson/rbenv.git dest={{ rbenv_root }} when: rbenv_path.rc != 0 - name: Install ruby-build sudo: yes git: repo=https://github.com/sstephenson/ruby-build.git dest={{ rbenv_root }}/plugins/ruby-build when: rbenv_path.rc != 0
roles/ruby/tasks/main.yml - name: create shims dir sudo: yes file: path={{
rbenv_root }}/shims state=directory when: rbenv_path.rc != 0 - name: create versions dir sudo: yes file: path={{ rbenv_root }}/versions state=directory when: rbenv_path.rc != 0 - name: change owner of install dir sudo: yes command: chgrp -R {{ app_user }} {{ rbenv_root }} when: rbenv_path.rc != 0 - name: change mode of install dir sudo: yes command: chmod -R g+rwxXs {{ rbenv_root }} when: rbenv_path.rc != 0
roles/ruby/tasks/main.yml - name: Set rbenv env file sudo: yes copy:
src=rbenv.sh dest=/etc/profile.d mode=0775 when: rbenv_path.rc != 0 - name: check ruby version shell: rbenv versions | grep {{ ruby_version }} > /dev/null ; echo $? ignore_errors: true register: ruby_is_installed changed_when: ruby_is_installed.stdout != '0' - name: Install ruby with rbenv shell: bash -lc "rbenv install {{ ruby_version }}" args: creates: "{{ rbenv_root }}/versions/{{ ruby_version }}/bin/ruby"
roles/ruby/tasks/main.yml - name: check ruby version shell: ruby -v |
grep {{ ruby_version }} > /dev/null ; echo $? register: is_correct_version changed_when: is_correct_version.stdout != '0' - name: Switch Ruby version shell: bash -lc "rbenv global {{ ruby_version }} && rbenv rehash" when: is_correct_version.stdout != '0' - name: update rubygems shell: bash -lc "rbenv exec gem update --system" - name: install common gems shell: bash -lc "rbenv exec gem install bundler io-console --no-ri --no-rdoc" args: creates: "{{ rbenv_root }}/shims/bundle"
CodeDeployઃఆͷ࡞
RAILS_ROOT/appspec.yml version: 0.0 os: linux files: - source: / destination:
/home/ec2-user/app permissions: - object: /home/ec2-user pattern: "**" owner: ec2-user group: ec2-user mode: 755
RAILS_ROOT/appspec.yml hooks: ApplicationStop: - location: script/codedeploy/deregister_from_elb.sh - location: script/codedeploy/application_stop.sh timeout:
300 runas: ec2-user BeforeInstall: - location: script/codedeploy/before_install.sh timeout: 300 runas: root
RAILS_ROOT/appspec.yml AfterInstall: - location: script/codedeploy/after_install.sh timeout: 3600 runas: ec2-user ApplicationStart:
- location: script/codedeploy/application_start.sh timeout: 3600 runas: ec2-user ValidateService: - location: script/codedeploy/verify_service.sh timeout: 3600 runas: ec2-user - location: script/codedeploy/register_with_elb.sh
ApplicationStop • σϓϩΠલʹΞϓϦΛఀࢭ͢Δ • ELBԼͷ߹ొղআ͢Δ • EC2ࣗΛstand byʹ͢Δ • deregister_from_elb.sh
awslabsϦϙͰ
ApplicationStop • application_stop.shͰదٓRailsΛఀࢭ͢ Δ • ͜ͷ࣌ͰELB͔Βִ͞Ε͍ͯΔͷͰࢭΊ ͳͯ͘ྑ͍
BeforeInstall • ιʔείʔυΛEC2ʹίϐʔ͢Δ • ओʹAnsible(ͱCapistrano)ͷ४උ • appspec.ymlͰrunas: rootΛΕͳ͍
BeforeInstall #!/bin/bash yum list installed python-pip &> /dev/null if [
$? != 0 ]; then yum install -y python-pip fi pip list | grep -q ansible if [ $? != 0 ]; then pip install ansible fi mkdir -p /data/app chown -R ec2-user:ec2-user /data/app
AfterInstall • ίϐʔͱunzipͷ࣍ʹ࣮ߦ͞ΕΔ • ࣗͷEC2λάΛಡΜͰઃఆϑΝΠϧΛμϯ ϩʔυͯ͠ධՁ
AfterInstall #!/bin/bash set -u METADATA=`ec2-describe-instances $(ec2-metadata -i | cut -d"
" -f 2) --region ap-northeast-1` BUCKET_NAME=`echo "$METADATA" | grep VariablesBucket | cut -f 5` KEY_NAME=`echo "$METADATA" | grep VariablesKey | cut -f 5` sudo aws s3api get-object --bucket $BUCKET_NAME \ --key $KEY_NAME $APPLICATION_VARIABLES_PATH \ --region ap-northeast-1 . $APPLICATION_VARIABLES_PATH /usr/local/bin/ansible-playbook $DESTINATION_PATH/ansible/site.yml \ -i $DESTINATION_PATH/ansible/codedeployhosts --connection=local
ApplicationStart • Railsͷىಈ४උͱىಈΛߦͳ͏ • ࠓճcapistranoͰٵऩ͍ͯ͠Δ
ApplicationStart #!/bin/bash set -u . /etc/profile.d/rbenv.sh . $APPLICATION_VARIABLES_PATH cd $DESTINATION_PATH
rbenv exec bundle exec cap local deploy
ValidateService • ΞϓϦέʔγϣϯͷىಈͱELBొΛߦͳ͏ • ҎԼͷεΫϦϓτ͕exit code 0ͳΒ࣍ͷ registerwithelb.sh͕Δ • registerwithelb.shAWSLabsͰެ։͞
Ε͍ͯΔ #!/bin/bash curl -s http://localhost/health_check
Cloud Formation Templateͷ࡞
ͦΕΛه͢ʹ ༨ന͕Γͳ͍
ͬͯΔ͜ͱ • ELBͷ࡞ • Launch Configͷ࡞ • User DataͰCodeDeploy AgentͷΠϯε
τʔϧ • Auto Scaling Groupͷ࡞ • Route53Ϩίʔυͷ࡞ ※CodeDeployϦιʔε࡞ͯ͠ͳ͍
Launch Config "UserData": { "Fn::Base64": { "Fn::Join": [ "", [
"#!/bin/bash -xe\n", "yum update -y aws-cfn-bootstrap; yum install -y aws-cli\n", "sed -i 's/Defaults requiretty/Defaults:root !requiretty/g' /etc/sudoers\n", "cd /home/ec2-user/\n", "aws s3 cp 's3://aws-codedeploy-us-east-1/latest/codedeploy-agent.noarch.rpm' . ", "|| error_exit 'Failed to download AWS CodeDeploy Agent.'\n", "yum -y install codedeploy-agent.noarch.rpm || error_exit 'Failed to install AWS CodeDeploy Agent.' \n" ] ] } },
CFn Create Stack
CodeDeployϦιʔεΛखಈͰ࡞ • ڥมshΛS3ʹஔ͘ • CFnͰͰ͖ͨASGΛࢦఆͯ͠Aplication/ DeploymentGroup࡞
σϓϩΠͯ͠ΈΔ
Ճཁ݅: ΑΓҰͷࣗಈԽ
ྲྀΕ • εΫϦϓτͰσϓϩΠ༻zipΛ࡞ • S3ʹஔ • LambdaͰCodeDeploy
εΫϦϓτͰσϓϩΠ༻zipΛ࡞ gulp.task('clean', function() { return del(['./tmp/dest']); }); gulp.task('zip', function() {
return gulp.src('**') .pipe(excludeGitignore()) .pipe(zip(bundleName + '.zip')) .pipe(gulp.dest('./tmp/dest')); }); gulp.task('upload', function(){ var publisher = awspublish.create({ params: { Bucket: BUCKET } }); return gulp.src('./tmp/dest/' + bundleName + '.zip') .pipe(publisher.publish()) .pipe(awspublish.reporter()); });
S3ʹzipΛஔ͘ͱಈ͘Lambda exports.handler = (event, context, callback) => { const message
= JSON.parse(event.Records[0].Sns.Message); const params = { applicationName: `my-application`, deploymentGroupName: `my-deployment-group`, revision: { revisionType: 'S3', s3Location: { bucket: message.bucketName, bundleType: 'zip', key: message.keyName } } };
S3ʹzipΛஔ͘ͱಈ͘Lambda codedeploy.createDeployment(params, (err, data) => { if (err) { console.log(err);
callback(err); } else { callback(null, data); } });
Ճཁ݅: ىಈΛૣ͘͢Δ
AMIΛͱΔ • σϓϩΠঢ়ଶͷAMI࡞ • CFnमਖ਼
Ճཁ݅: B-G σϓϩΠ
• ELB+ASGΛDeploymentGroupΛ2ͭ࡞ • CodeDeloyޭ࣌ʹSNSܦ༝ͰLambdaΛىಈ • LambdaͰRoute53 ALIASϨίʔυͷ͖ઌΛ ม͑Δ
·ͱΊ
CodeDeployͰҎԼΛୡՄೳ • AnsibleγΣϧεΫϦϓτͷφϨοδΛస༻ Ͱ͖Δ • χʔζʹ߹ΘͤͨσϓϩΠγεςϜΛ࡞ΕΔ