Automate deploying a Docker Application to AWS by Travis CI

Trong bài viết này mình sẽ sử dụng một ứng dụng React basic cho frontend , Docker cho việc container hoá và AWS cho việc triển khai ứng dụng.

Yêu cầu:

  • A Github account
  • A minimum of a free tier AWS account.
  • A basic knowledge of Docker

Travis-CI là một dịch vụ tích hợp liên tục (CI) được lưu trữ được sử dụng để xây dựng và thử nghiệm các dự án phần mềm được lưu trữ tại GitHub.

Về cơ bản, nó giúp các nhà phát triển tự động hóa quá trình triển khai source code của mình từ local lên môi trường trực tiếp trong khi vẫn đảm bảo tất cả các thử nghiệm đã đặt của ứng dụng được thông qua trước khi  triển khai lên production.

                                                Tổng quan về sơ đồ hoạt động của ứng dụng

Bước 1: React

Tôi đã sử dụng gói npm có tên là create-react-app để nhanh chóng tạo ra ứng dụng bằng cách chạy lệnh create-react-app sample-app

Sau khi hoàn thành, bạn sẽ thấy một cấu trúc thư mục như thế này:

Bước 2 : Docker

Tại thời điểm này, chúng ta sẽ cần tạo một docker image cho ứng dụng này và để làm điều này, chúng ta sẽ thêm hai tệp có tên bên dưới vào thư mục gốc của ứng dụng:

  • Dockerfile - Được sử dụng để xây dựng image có chứa phiên bản tối ưu hóa của ứng dụng này.
  • Dockerfile.dev - Được sử dụng để xây dựng hình ảnh có chứa phiên bản phát triển sẽ được sử dụng để chạy trên môi trường development.

Tệp Dockerfile chứa các hướng dẫn mà docker sử dụng để xây dựng hình ảnh của ứng dụng.

Để mọi thứ dễ hiểu hơn, dưới đây là DockerFile tôi sử dụng:

  • DockerFile
#Split everything the build into two steps
FROM node:alpine as builder
# Above, we set the base image for this first stage as a light weigh node called alpine

WORKDIR '/app'
# Above we set the build environment as a folder called /app in the docker container to prevent clashes

COPY package.json .
# To prevent repeated npm installs anytime we make any change, we'd copy over the package.json and install things first

RUN npm i

COPY . .
# Copy the rest of the project over to the /app folder in the container

RUN npm run build
# Build the production version of our app in the container

FROM nginx 
# The image needs nginx to run on aws

EXPOSE 80 
#Nginx runs on port 80, so elastic beanstalk uses the expose command to expose this port

COPY --from=builder /app/build /usr/share/nginx/html

# Copy the content of the builder step, move the contents of build folder into the html folder in this nginx container
# That's where our app would run from in aws

# No need to specify a command to start nginx as it gets started by default when a container with the image starts
  • Dockerfile.dev
FROM node:alpine
# Above, we set the base image as a light weight node image called alpine

WORKDIR '/app'
# Above we set the build environment as a folder called /app in the docker container to prevent clashes

COPY package.json .
# To prevent repeated npm installs anytime we make any change, we'd copy over the package.json and install things first

RUN npm i

COPY . .
# Copy the rest of the project over to the /app folder in the container

CMD ["npm", "start"]
# Here we are setting the default command when a container is built and started up from this our image

Tại thời điểm này, bạn nên tạo một repository trên github (Bạn có thể đặt tên cho nó là docker-react giống như tôi cho tính nhất quán) và push source code của mình lên đó.

Bây giờ chúng ta cần kết nối repository của chúng ta với travis-ci và để làm điều này, chúng ta sẽ chuyển sang bước 3.

Bước 3: Config Travis CI

Tôi giả sử bạn đã có một tài khoản với Travis-CI bằng tài khoản Github của bạn. Điều này mang lại cho ta quyền truy cập cần thiết vào repository của bạn.

Tiếp theo, nhấp vào biểu tượng hồ sơ của bạn> cài đặt, sau đó bật repository docker-react mà chúng ta vừa tạo ở Github.

Điều này nói với Travis-CI sẽ bắt đầu theo dõi repository của chúng ta. Nhưng để làm điều này, chúng ta cần một tệp YAML có tên .travis.yml vào ứng dụng vì điều này sẽ chứa các cài đặt về những gì bạn muốn Travis-CI thực hiện với source code của bạn khi quá trình xây dựng được kích hoạt.

Dưới đây là một số hướng dẫn bạn nên thêm vào tệp .travis.yml của mình:

sudo: required 
language: node_js
node_js:
    - "stable"
    
services: 
    - docker

before_install: 
    - docker build -t nhandd/sample-app -f Dockerfile.dev .
script:     
    - docker run -e CI=true nhandd/sample-app npm run test -- --coverage
  • sudo: required - Travis CI yêu cầu người dùng phải là user root
  • language: node_js - Xác định ngôn ngữ nên được sử dụng trong việc xây dựng ứng dụng
  • services - Được sử dụng để nói với Travis-CI rằng chúng ta cần một phiên bản docker chạy cho ứng dụng này.
  • before_install -  Các việc cần làm với  source code của bạn trước khi chạy testing hoặc deploy lên môi trường dev (Hướng dẫn ở đây xây dựng docker image bằng tệp Dockerfile.dev của tôi và gắn với tên nhandd/sample-app)
  • script : Một loạt các tập lệnh để chạy trước khi triển khai mã của bạn.

Bước 4: AWS Elastic Beanstalk

AWS Elastic Beanstalk là một dịch vụ dễ sử dụng để triển khai và scale các ứng dụng và dịch vụ web được phát triển với Java ,. NET, PHP, Node. js, Python, Ruby, Go và Docker trên các web server quen thuộc như Apache, Nginx, Passenger và IIS.

Chúng ta cần đăng nhập vào AWS, đi đến các dịch vụ và chọn Elastic Beanstalk sau đó chọn Create Application như được thấy dưới đây:

Nhập tên ứng dụng và chọn platform là Docker  sau đó nhấn Create Application như hình dưới:

Nếu mọi thứ diễn ra theo đúng kế hoạch, bạn sẽ thấy một cái gì đó như thế này khi nó kết thúc:

Bước 5 : AWS IAM

Identity and Access Management (IAM) cung cấp một cách để các nền tảng bên ngoài truy cập các elastic beanstalk apps trong tài khoản AWS của chúng ta.

Để làm điều này, chúng ta cần tạo một IAM user  và cấp cho người dùng các đặc quyền phù hợp.

Go to Services(at the top left) > IAM > users > Add user on the page.

Tôi đã sử dụng sample-docker-react làm tên người dùng và tất cả các quyền liên quan đến elasticbeanstalk vì đó là những gì ứng dụng này cần.

Khi thành công, bạn đã thấy một bảng hiển thị cho bạn AccessKeyIDSecretAccessKey như xem bên dưới.

Bước 6 : AWS S3 Buckets

Amazon S3 hoặc Amazon Simple Storage Service là dịch vụ được cung cấp bởi Amazon Web Services (AWS) cung cấp lưu trữ đối tượng thông qua giao diện dịch vụ web.

Ngoài ra, trong khi tạo elastic beanstalk environment, AWS chọn một vị trí máy chủ gần bạn nhất để lưu trữ nó (Bạn cũng có thể chọn một vị trí khác).

Ngoài ra, sau khi môi trường được tạo, S3 cũng được tạo có tên chứa định danh của vị trí máy chủ bạn sử dụng (ví dụ: us-east-1, us-west-1) và nó được sử dụng để lưu trữ các ứng dụng mà bạn đã triển khai trong môi trường hiện tại trong cùng một vị trí máy chủ.

Thứ hai, bạn cần chỉ định một thư mục (còn gọi là backet path trong travis) sẽ được travis-ci sử dụng để triển khai.

Goto Services > Storage > S3

Chọn nhóm có tên có mã định danh vị trí máy chủ của môi trường của bạn trong tên đó.

Tạo một thư mục và bạn có thể đặt tên nó cùng tên với ứng dụng của bạn (sample-docker-react) sự lựa chọn tên này là tùy chọn và tôi làm điều đó để giúp tôi nhớ ứng dụng mà nó dùng cho ứng dụng nào.

Bước 7 : Quay lại với Travis-CI

Bạn cần phải thêm AccessKeyIDSecretAccessKey làm biến môi trường trong Travis-CI.

Đi đến bảng điều khiển của bạn và chọn the sample-docker-react repository => click các tùy chọn ở trên cùng bên phải => click cài đặt.

Trên trang này bạn AWS_ACCESS_KEY and AWS_SECRET_KEY like I have done:

Bước 8 : Quay lại với React

Chúng ta cần cập nhật tệp .travis-yml với các hướng dẫn để triển khai mã của chúng ta và sau đó đẩy sang Github.

Cập nhật của bạn với những điều sau đây:

deploy:
  provider: elasticbeanstalk
  region: "your-server-location"
  app: "sample-docker-react"
  env: "SampleDockerReact-env"
  bucket_name: "elasticbeanstalk-us-east-2-XXXXXXXXXXXX"
  bucket_path: "sample-app"
  on:
    branch: master
  access_key_id: $AWS_ACCESS_KEY
  secret_access_key:
    secure: "$AWS_SECRET_KEY"
  • deploy: Cho Travis-CI biết cách triển khai ứng dụng của bạn.
  • provider: Platform  sử dụng.
  • region: Nơi server elastic beanstalk app bạn khởi tạo.
  • app: Tên ứng dụng
  • bucket_name: Tên bucket bạn khởi tạo trong S3.
  • bucket_path: Thư mục chúng ta khởi tạo để nhận từ travis-ci.
  • on: Branch để build.
  • access_key_id: IAM access key generated in AWS nhưng được lưu trong travis ci
  • secret_access_key: IAM secret key generated in IAM of AWS nhưng được lưu trong travis ci

Bây giờ tệp .travis.yml của chúng tôi sẽ trông giống như:


sudo: required #Travis ci requires the user to be with elevated permission

language: node_js
node_js:
    - "stable"
    
services: 
    - docker #Our use of travis ci needs an instance of docker to be running

before_install: #Things to do with your code on travis ci before running tests or deploying your code
    - docker build -t nhandd/sample-docker-react -f Dockerfile.dev . #Used the .dev dockerfile cos we need to run the tests in travis ci and the test image is in that .dev file

script:     
    - docker run -e CI=true nhandd/sample-docker-react npm run test -- --coverage

deploy: #This deploys the whole folder onto elasticbeanstalk so it's the production Dockerfile that would be used by elasticbeanstalk to startup this app
    provider: elasticbeanstalk
    region: "" #region you selected when creating the elb application
    app: "sample-docker-react" #the aws elb app name
    env: "SampleDockerReact-env" #the aws elb app environment
    bucket_name: "elasticbeanstalk-us-east-2-XXXXXXXXXXXX" #s3 storage location for all apps deployed to this region
    bucket_path: "sample-docker-react" #name of the folder where this app you're targeting is located or going to exist
    on:
        branch: master #Only deploy when master branch is updated
    access_key_id: $AWS_ACCESS_KEY #Environment variable generated in IAM of AWS but stored in travis ci
    secret_access_key:
        secure: "$AWS_SECRET_KEY" # Another environment variable generated in IAM of AWS but stored in travis ci

Bước 9 : Push to Git

Kiểm tra lại một lần nữa các tệp của bạn và thiết lập để đảm bảo bạn đã làm tất cả những gì tôi đã nói trong phần hướng dẫn này sau đó Add, commit và push các bản cập nhật của bạn lên repo trên github.

Vì chúng ta đã thêm một tệp .travis.yml, travis-ci sẽ nhận bản cập nhật trong vài giây và kích hoạt bản dựng.

Sau khi xây dựng thành công, hãy truy cập ứng dụng của bạn trên AWS và bạn sẽ thấy nó được cập nhật với mã mới từ travis, xây dựng docker image và khởi động ứng dụng có thể truy cập khi bạn nhấp vào liên kết được cung cấp.

Bây giờ bất cứ khi nào chúng tôi cập nhật nhánh master ứng dụng của mình, travis-ci sẽ nhận các thay đổi và cập nhật ứng dụng của chúng ta trong AWS.

Nếu bạn thực hiện thành công theo hướng dẫn này, cảm ơn rất nhiều vì đã đọc bài!