Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift で開発した Web アプリケーションを Amazon EC2 Container Services で運用する

ngs
March 07, 2016

Swift で開発した Web アプリケーションを Amazon EC2 Container Services で運用する

ngs

March 07, 2016
Tweet

More Decks by ngs

Other Decks in Technology

Transcript

  1. Swift Ͱ։ൃͨ͠ Web ΞϓϦέʔγϣϯΛ Amazon EC2 Container Services Ͱӡ༻͢Δ Atsushi

    Nagase @ngs / http://ja.ngs.io/ https://one-team.com/products/
  2. BUILD • sbt assembly • docker build TEST • sbt

    test:test • cd serverspec && rspec DEPLOY • docker push • aws ecs register-task-definition • aws ecs update-service
  3. $ cat Procfile web: Swifton-TodoApp --workers 3 --bind 0.0.0.0:$PORT $

    cat app.json { "name": "Swifton TodoApp Example", "description": "An example TodoApp using Swifton web framework on Heroku.", "repository": "https://github.com/necolt/Swifton-TodoApp", "website": "https://github.com/necolt/Swifton-TodoApp", "keywords": [“swifton", "curassow"], "buildpacks": [{ "url": “https://github.com/kylef/heroku-buildpack-swift" }] }
  4. FROM ubuntu:14.04 MAINTAINER [email protected] ENV SWIFT_BRANCH development ENV SWIFT_VERSION DEVELOPMENT-SNAPSHOT-2016-02-08-a

    ENV SWIFT_PLATFORM ubuntu14.04 RUN apt-get update && \ apt-get install -y build-essential wget clang libedit-dev python2.7 python2.7-dev libicu52 rsync libxml2 git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import - && \ gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift RUN SWIFT_ARCHIVE_NAME=swift-$SWIFT_VERSION-$SWIFT_PLATFORM && \ SWIFT_URL=https://swift.org/builds/$SWIFT_BRANCH/$(echo "$SWIFT_PLATFORM" | tr -d .)/swift-$SWIFT_VERSION/ $SWIFT_ARCHIVE_NAME.tar.gz && \ wget $SWIFT_URL && \ wget $SWIFT_URL.sig && \ gpg --verify $SWIFT_ARCHIVE_NAME.tar.gz.sig && \ tar -xvzf $SWIFT_ARCHIVE_NAME.tar.gz --directory / --strip-components=1 && \ rm -rf $SWIFT_ARCHIVE_NAME* /tmp/* /var/tmp/* ENV PATH /usr/bin:$PATH RUN mkdir -p /swifton WORKDIR /swifton ADD . /swifton RUN swift build --configuration release EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  5. FROM ubuntu:14.04 MAINTAINER [email protected] ENV SWIFT_BRANCH development ENV SWIFT_VERSION DEVELOPMENT-SNAPSHOT-2016-02-08-a

    ENV SWIFT_PLATFORM ubuntu14.04 RUN apt-get update && \ apt-get install -y build-essential wget clang libedit-dev python2.7 python2.7-dev libicu52 rsync libxml2 git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import - && \ gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift RUN SWIFT_ARCHIVE_NAME=swift-$SWIFT_VERSION-$SWIFT_PLATFORM && \ SWIFT_URL=https://swift.org/builds/$SWIFT_BRANCH/$(echo "$SWIFT_PLATFORM" | tr -d .)/swift-$SWIFT_VERSION/ $SWIFT_ARCHIVE_NAME.tar.gz && \ wget $SWIFT_URL && \ wget $SWIFT_URL.sig && \ gpg --verify $SWIFT_ARCHIVE_NAME.tar.gz.sig && \ tar -xvzf $SWIFT_ARCHIVE_NAME.tar.gz --directory / --strip-components=1 && \ rm -rf $SWIFT_ARCHIVE_NAME* /tmp/* /var/tmp/* ENV PATH /usr/bin:$PATH RUN mkdir -p /swifton WORKDIR /swifton ADD . /swifton RUN swift build --configuration release EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  6. FROM ubuntu:14.04 MAINTAINER [email protected] ENV SWIFT_BRANCH development ENV SWIFT_VERSION DEVELOPMENT-SNAPSHOT-2016-02-08-a

    ENV SWIFT_PLATFORM ubuntu14.04 RUN apt-get update && \ apt-get install -y build-essential wget clang libedit-dev python2.7 python2.7-dev libicu52 rsync libxml2 git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import - && \ gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift RUN SWIFT_ARCHIVE_NAME=swift-$SWIFT_VERSION-$SWIFT_PLATFORM && \ SWIFT_URL=https://swift.org/builds/$SWIFT_BRANCH/$(echo "$SWIFT_PLATFORM" | tr -d .)/swift-$SWIFT_VERSION/ $SWIFT_ARCHIVE_NAME.tar.gz && \ wget $SWIFT_URL && \ wget $SWIFT_URL.sig && \ gpg --verify $SWIFT_ARCHIVE_NAME.tar.gz.sig && \ tar -xvzf $SWIFT_ARCHIVE_NAME.tar.gz --directory / --strip-components=1 && \ rm -rf $SWIFT_ARCHIVE_NAME* /tmp/* /var/tmp/* ENV PATH /usr/bin:$PATH RUN mkdir -p /swifton WORKDIR /swifton ADD . /swifton RUN swift build --configuration release EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  7. FROM ubuntu:14.04 MAINTAINER [email protected] ENV SWIFT_BRANCH development ENV SWIFT_VERSION DEVELOPMENT-SNAPSHOT-2016-02-08-a

    ENV SWIFT_PLATFORM ubuntu14.04 RUN apt-get update && \ apt-get install -y build-essential wget clang libedit-dev python2.7 python2.7-dev libicu52 rsync libxml2 git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import - && \ gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift RUN SWIFT_ARCHIVE_NAME=swift-$SWIFT_VERSION-$SWIFT_PLATFORM && \ SWIFT_URL=https://swift.org/builds/$SWIFT_BRANCH/$(echo "$SWIFT_PLATFORM" | tr -d .)/swift-$SWIFT_VERSION/ $SWIFT_ARCHIVE_NAME.tar.gz && \ wget $SWIFT_URL && \ wget $SWIFT_URL.sig && \ gpg --verify $SWIFT_ARCHIVE_NAME.tar.gz.sig && \ tar -xvzf $SWIFT_ARCHIVE_NAME.tar.gz --directory / --strip-components=1 && \ rm -rf $SWIFT_ARCHIVE_NAME* /tmp/* /var/tmp/* ENV PATH /usr/bin:$PATH RUN mkdir -p /swifton WORKDIR /swifton ADD . /swifton RUN swift build --configuration release EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  8. $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

    <none> <none> sha256:c35f9 30 seconds ago 893.2 MB
  9. $ sudo apt-get install libicu-dev clang-3.6 jq $ sudo update-alternatives

    --install \ /usr/bin/clang clang /usr/bin/clang-3.6 100 $ sudo update-alternatives --install \ /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100
  10. . |-- .build | `-- release | `-- Swifton-TodoApp |--

    Views | `-- Todos | |-- Edit.html.stencil | |-- Index.html.stencil | |-- New.html.stencil | `-- Show.html.stencil `-- swift `-- usr `-- lib `-- swift `-- linux |-- libFoundation.so |-- libXCTest.so |-- libswiftCore.so |-- libswiftGlibc.so `-- libswiftSwiftOnoneSupport.so
  11. . |-- .build | `-- release | `-- Swifton-TodoApp |--

    Views | `-- Todos | |-- Edit.html.stencil | |-- Index.html.stencil | |-- New.html.stencil | `-- Show.html.stencil `-- swift `-- usr `-- lib `-- swift `-- linux |-- libFoundation.so |-- libXCTest.so |-- libswiftCore.so |-- libswiftGlibc.so `-- libswiftSwiftOnoneSupport.so
  12. . |-- .build | `-- release | `-- Swifton-TodoApp |--

    Views | `-- Todos | |-- Edit.html.stencil | |-- Index.html.stencil | |-- New.html.stencil | `-- Show.html.stencil `-- swift `-- usr `-- lib `-- swift `-- linux |-- libFoundation.so |-- libXCTest.so |-- libswiftCore.so |-- libswiftGlibc.so `-- libswiftSwiftOnoneSupport.so
  13. . |-- .build | `-- release | `-- Swifton-TodoApp |--

    Views | `-- Todos | |-- Edit.html.stencil | |-- Index.html.stencil | |-- New.html.stencil | `-- Show.html.stencil `-- swift `-- usr `-- lib `-- swift `-- linux |-- libFoundation.so |-- libXCTest.so |-- libswiftCore.so |-- libswiftGlibc.so `-- libswiftSwiftOnoneSupport.so
  14. FROM ubuntu:14.04 MAINTAINER [email protected] RUN apt-get update && apt-get install

    -y libicu52 libxml2 curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ENV APP_DIR /var/www/app RUN mkdir -p ${APP_DIR} WORKDIR ${APP_DIR} ADD . ${APP_DIR} RUN ln -s ${APP_DIR}/swift/usr/lib/swift/linux/*.so /usr/lib EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  15. FROM ubuntu:14.04 MAINTAINER [email protected] RUN apt-get update && apt-get install

    -y libicu52 libxml2 curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ENV APP_DIR /var/www/app RUN mkdir -p ${APP_DIR} WORKDIR ${APP_DIR} ADD . ${APP_DIR} RUN ln -s ${APP_DIR}/swift/usr/lib/swift/linux/*.so /usr/lib EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  16. FROM ubuntu:14.04 MAINTAINER [email protected] RUN apt-get update && apt-get install

    -y libicu52 libxml2 curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ENV APP_DIR /var/www/app RUN mkdir -p ${APP_DIR} WORKDIR ${APP_DIR} ADD . ${APP_DIR} RUN ln -s ${APP_DIR}/swift/usr/lib/swift/linux/*.so /usr/lib EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  17. FROM ubuntu:14.04 MAINTAINER [email protected] RUN apt-get update && apt-get install

    -y libicu52 libxml2 curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ENV APP_DIR /var/www/app RUN mkdir -p ${APP_DIR} WORKDIR ${APP_DIR} ADD . ${APP_DIR} RUN ln -s ${APP_DIR}/swift/usr/lib/swift/linux/*.so /usr/lib EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  18. FROM ubuntu:14.04 MAINTAINER [email protected] RUN apt-get update && apt-get install

    -y libicu52 libxml2 curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ENV APP_DIR /var/www/app RUN mkdir -p ${APP_DIR} WORKDIR ${APP_DIR} ADD . ${APP_DIR} RUN ln -s ${APP_DIR}/swift/usr/lib/swift/linux/*.so /usr/lib EXPOSE 8000 CMD .build/release/Swifton-TodoApp
  19. $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

    <none> <none> sha256:c35f9 2 minutes ago 893.2 MB <none> <none> sha256:0d31d 30 seconds ago 245.8 MB
  20. require 'spec_helper' describe port(8000) do it { should be_listening }

    end describe command('curl -i -s -H \'Accept: text/html\' http://0.0.0.0:8000/') do its(:exit_status) { is_expected.to eq 0 } its(:stdout) { is_expected.to contain 'HTTP/1.1 200 OK' } its(:stdout) { is_expected.to contain '<h1>Listing Todos</h1>' } end 1.upto(2) do|n| describe command("curl -i -s -H \'Accept: text/html\' http://0.0.0.0:8000/todos -d \'title=Test#{n}\'") do its(:exit_status) { is_expected.to eq 0 } its(:stdout) { is_expected.to contain 'HTTP/1.1 302 FOUND' } its(:stdout) { is_expected.to contain 'Location: /todos' } end end describe command('curl -i -s -H \'Accept: text/html\' http://0.0.0.0:8000/todos') do its(:exit_status) { is_expected.to eq 0 } its(:stdout) { is_expected.to contain 'HTTP/1.1 200 OK' } its(:stdout) { is_expected.to contain '<h1>Listing Todos</h1>' } its(:stdout) { is_expected.to contain '<td>Test1</td>' } its(:stdout) { is_expected.to contain '<td>Test2</td>' } its(:stdout) { is_expected.to contain '<td><a href="/todos/0">Show</a></td>' } its(:stdout) { is_expected.to contain '<td><a href="/todos/1">Show</a></td>' } end
  21. $ cd serverspec && export DOCKER_CONTAINER=serverspec && bundle exec rspec

    Port "8000" should be listening Command "curl -i -s -H 'Accept: text/html' http://0.0.0.0:8000/" exit_status should eq 0 stdout should contain "HTTP/1.1 200 OK" stdout should contain "<h1>Listing Todos</h1>" Command "curl -i -s -H 'Accept: text/html' http://0.0.0.0:8000/todos -d 'title=Test1'" exit_status should eq 0 stdout should contain "HTTP/1.1 302 FOUND" stdout should contain "Location: /todos" Command "curl -i -s -H 'Accept: text/html' http://0.0.0.0:8000/todos -d 'title=Test2'" exit_status should eq 0 stdout should contain "HTTP/1.1 302 FOUND" stdout should contain "Location: /todos" Command "curl -i -s -H 'Accept: text/html' http://0.0.0.0:8000/todos" exit_status should eq 0 stdout should contain "HTTP/1.1 200 OK" stdout should contain "<h1>Listing Todos</h1>" stdout should contain "<td>Test1</td>" stdout should contain "<td>Test2</td>"
  22. #!/bin/sh set -eu APP_NAME=swifton-example- UPPER_ENV_NAME=$(echo $ENV_NAME | awk '{print toupper($0)}')

    CLUSTER="${APP_NAME}${ENV_NAME}" TASK_FAMILY="${APP_NAME}${ENV_NAME}" SERVICE_NAME="${APP_NAME}service-${ENV_NAME}" LOADBALANCER_NAME="${APP_NAME}${ENV_NAME}" CONTAINER_PORT=8000 CONTAINER_NAME=$CONTAINER_NAME CONTAINER_PORT=$CONTAINER_PORT APP_NAME=$APP_NAME \ erb ecs-task-definitions/service.json.erb > .ecs-task-definition.json TASK_DEFINITION_JSON=$(aws ecs register-task-definition --family $TASK_FAMILY \ --cli-input-json "file://$(pwd)/.ecs-task-definition.json") TASK_REVISION=$(echo $TASK_DEFINITION_JSON | jq .taskDefinition.revision) SERVICE_JSON=$(aws ecs describe-services --services $SERVICE_NAME --cluster $CLUSTER) if [ $(echo $SERVICE_JSON | jq '.services | length') = "0" ]; then SERVICE_JSON=$(aws ecs create-service --cluster ${CLUSTER} --service ${SERVICE_NAME} \ --task-definition ${TASK_FAMILY}:${TASK_REVISION} --desired-count 1 \ --load-balancers loadBalancerName=${LOADBALANCER_NAME},containerName=${CONTAINER_NAME},containerPort=$ {CONTAINER_PORT} --role ecs-operation) else DESIRED_COUNT=$(echo $SERVICE_JSON | jq '.services[0].desiredCount') if [ ${DESIRED_COUNT} = "0" ]; then DESIRED_COUNT="1" fi SERVICE_JSON=$(aws ecs update-service --cluster ${CLUSTER} --service ${SERVICE_NAME} --task-definition $ {TASK_FAMILY}:${TASK_REVISION} --desired-count ${DESIRED_COUNT}) fi echo $SERVICE_JSON | jq .