Dockerizing ứng dụng khởi động mùa xuân

Docker ở đây, Docker ở đó, tôi thấy Dockers ở khắp mọi nơi.
Trong bài đăng này, tôi sẽ mô tả quá trình di chuyển một ứng dụng Spring Boot sang Docker. Chúng tôi sẽ bắt đầu với việc sửa đổi một tệp xây dựng, sau đó chúng tôi sẽ tạo một Dockerfile để nó có thể chạy cục bộ. Cuối cùng, chúng tôi sẽ xuất bản hình ảnh của mình trong DockerHub .
Giới thiệu
Một vài tháng trước, tôi đã bắt đầu một dự án cá nhân mới có tên JVM Bloggers để giúp các lập trình viên Ba Lan truyền bá tin tức về các bài đăng blog mới của họ. Ban đầu, ứng dụng Spring Boot này được lưu trữ trên máy cục bộ của tôi, nhưng tôi đã chuyển nó sang tài khoản miễn phí trên Heroku .
Và trong những tuần đầu tiên, tôi hài lòng. Ứng dụng không phải trực tuyến 24/7 vì vậy ngủ 8 giờ mỗi ngày (giới hạn của tài khoản Heroku miễn phí) không phải là vấn đề lớn và giới hạn bộ nhớ 500 MB cũng không giới hạn tôi. Nhưng khi JVM Bloggers phát triển, tôi bắt đầu gặp phải các vấn đề kỳ lạ với việc sử dụng bộ nhớ: ứng dụng bắt đầu ngốn 500-550MB và rất khó tìm ra nguồn gốc của hành vi này. Tôi thậm chí còn để ứng dụng chạy trên máy cục bộ của mình với một hồ sơ đính kèm nhưng vẫn không tìm thấy bất cứ điều gì đáng ngờ.
Vấn đề về dấu chân bộ nhớ trở nên khó chịu vì tôi phải theo dõi ứng dụng và khởi động lại nó sau mỗi 1-2 ngày và do bản chất của Heroku, tôi không thể chỉ ssh vào máy chủ và gỡ lỗi hoặc đính kèm một hồ sơ vào một quy trình đang chạy. Rõ ràng là nếu tôi định thêm nhiều tính năng hơn cho JVM Bloggers, tôi phải chuyển nó sang một thứ linh hoạt hơn - một máy Linux với Docker.
Docker
Ngày nay Docker là một chủ đề rất phổ biến đối với nhiều nhà phát triển, đặc biệt là trong các dự án chuyển sang kiến trúc microservices. Nhưng tính năng thú vị nhất từ góc độ vấn đề của tôi là khả năng tạo ra một hình ảnh tiêu chuẩn hóa của ứng dụng của tôi và chạy nó trong một môi trường khác mà không phải lo lắng về sự khác biệt. Một hình ảnh có thể được triển khai cục bộ hoặc trên hầu hết mọi máy Linux, vì vậy với Docker, tôi có thể kiểm tra ứng dụng của mình cục bộ và triển khai nó trên AWS hoặc một nơi nào khác mà không gặp nhiều rắc rối.
Di cư
Đầu tiên, chúng ta phải thêm một số phụ thuộc và nhiệm vụ mới vào tập lệnh build.gradle của mình :
buildscript {
// ...
dependencies {
// ...
classpath('se.transmode.gradle:gradle-docker:1.2')
}
}
// ...
group = 'tdziurko' // this will be my login at DockerHub (more about it later in this post)
task buildDocker(type: Docker, dependsOn: build) { // this task will build our Docker image
push = true
applicationName = jar.baseName
dockerfile = file('src/main/docker/Dockerfile')
doFirst {
copy {
from jar
into stageDir
}
}
}
Trong dòng 16, chúng tôi đã chỉ định vị trí của Dockerfile của chúng tôi, vì vậy bây giờ đã đến lúc tạo một tệp ở đó.
Tạo Dockerfile
Dockerfile là một tệp cấu hình chỉ định cách tạo hình ảnh Docker của chúng tôi để chúng tôi có thể triển khai sau này.
FROM java:8
MAINTAINER email@example.com
VOLUME /tmp
EXPOSE 8080
ENV USER_NAME blogger
ENV APP_HOME /home/$USER_NAME/app
RUN useradd -ms /bin/bash $USER_NAME
RUN mkdir $APP_HOME
ADD jvm-bloggers-0.5.0.jar $APP_HOME/jvm-bloggers.jar
RUN chown $USER_NAME $APP_HOME/jvm-bloggers.jar
USER $USER_NAME
WORKDIR $APP_HOME
RUN bash -c 'touch jvm-bloggers.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","jvm-bloggers.jar"]
Hãy để tôi giải thích tệp này từng bước:
- TỪ java: 8 : hình ảnh cơ sở của chúng tôi, nó giống như từ khóa mở rộng trong Java. Ở đây chúng tôi muốn tạo cơ sở cho hình ảnh với Java 8 được cài đặt
- VOLUME / tmp : thư mục được gắn kết nơi ứng dụng của chúng tôi có thể ghi thứ gì đó vào đĩa
- EXPOSE 8080 : số cổng ứng dụng của chúng tôi sẽ được khởi động và nó sẽ có sẵn từ bên ngoài vùng chứa Docker
- ENV USER_NAME blogger : biến trợ giúp với tên người dùng mà chúng tôi sẽ sử dụng để chạy ứng dụng của mình
- ENV APP_HOME / home / $ USER_NAME / app : biến trình trợ giúp tiếp theo với thư mục nơi đặt ứng dụng của chúng tôi
- RUN useradd -ms / bin / bash $ USER_NAME : tạo người dùng có tên được xác định bằng $ USER_NAME
- RUN mkdir $ APP_HOME : tạo thư mục ứng dụng
- THÊM jvm-bloggers-0.5.0.jar $ APP_HOME / jvm-bloggers.jar : thêm fat-jar vào hình ảnh của chúng tôi và đặt nó vào $ APP_HOME
- RUN chown $ USER_NAME $ APP_HOME / jvm-bloggers.jar : tất cả các lệnh trước đó đã được thực thi dưới dạng ROOT, vì vậy chúng tôi cần thay đổi chủ sở hữu của tệp jar của mình thành $ USER_NAME . Nói chung sử dụng ROOT trong Docker được coi là một cách tiếp cận sai lầm vì bảo mật.
- USER $ USER_NAME; WORKDIR $ APP_HOME : thay đổi người dùng và thư mục làm việc thành những thư mục mà chúng tôi muốn sử dụng để chạy ứng dụng của mình
- RUN bash -c 'touch jvm-bloggers.jar' : chạm vào tệp của chúng tôi để tệp có thời gian sửa đổi
- ENTRYPOINT [“java”, “- Djava.security.egd = file: / dev /./ urandom”, “- jar”, “jvm-bloggers.jar”] : thực thi fat-jar của chúng ta (urandom dành cho nguồn Tomcat của Sự hỗn loạn)
Chạy hình ảnh Docker cục bộ
Bây giờ chúng tôi đã có mọi thứ sẵn sàng để xây dựng và khởi chạy hình ảnh Docker của mình.
./gradlew clean build buildDocker
Phản ứng:
:buildDocker FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':buildDocker'.
> Docker execution failed
Command line [docker push tdziurko/jvm-bloggers:latest] returned:
unauthorized: access to the requested resource is not authorized
Task buildDocker không thành công vì chúng tôi không có tài khoản trên DockerHub hoặc chúng tôi chưa đăng nhập ở đó. nhưng nếu bạn kiểm tra hình ảnh địa phương ...
docker images
... bạn sẽ thấy rằng hình ảnh mới nhất của chúng tôi có thẻ đã sẵn sàng để sử dụng:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
tdziurko/jvm-bloggers latest a09f884c5aa9 11 minutes ago 785.6 MB
Vì vậy, chúng tôi có thể chạy nó trong vùng chứa Docker bằng lệnh sau:
docker run -p 8080:8080 --add-host=database:<your_local_db_host> -e jasypt.encryptor.password="<secretPassword>" -e spring.profiles.active="dev" tdziurko/jvm-bloggers:latest
Một lần nữa, một số đoạn cần được giải thích chi tiết hơn:
- —Add-host = database: <your_local_db_host> : thêm địa chỉ vào / etc / hosts trong vùng chứa, cơ sở dữ liệu var phải là địa chỉ của cơ sở dữ liệu của chúng ta, ví dụ: 192.168.0.101
- -e jasypt.encryptor.password = “” : Mật khẩu jasypt để giải mã một số giá trị từ các tệp * .properties, -e thêm nó dưới dạng biến env vào vùng chứa
- -e spring.profiles.active = “dev” : Cấu hình Spring Boot. dev là một được sử dụng để chạy ứng dụng cục bộ
Sau một vài giây, bạn sẽ thấy rằng ứng dụng của chúng tôi đã khởi động và nó đang chạy trong vùng chứa Docker.
Xuất bản lên DockerHub
Có sẵn hình ảnh Docker cục bộ là được miễn là bạn chỉ định chơi với hình ảnh đó trên máy tính của riêng mình, nhưng vì chúng tôi đang hướng tới việc triển khai AWS nên chúng tôi cần xuất bản hình ảnh của mình lên DockerHub để nó có thể truy cập được từ bất kỳ máy Linux nào.
Trước tiên, cần tạo một tài khoản ở đó ( trong trường hợp của tôi là tdziurko ) và đăng nhập bằng ứng dụng khách Docker để chúng tôi có thể xuất bản nó.
$ docker login
Username: tdziurko
Password:
Email: tomek@example.com
WARNING: login credentials saved in /Users/tomek/.docker/config.json
Login Succeeded
Bây giờ chúng ta có thể xây dựng lại ứng dụng của mình để đẩy hình ảnh lên DockerHub:
./gradlew clean build buildDocker
Sau một vài phút, chúng tôi sẽ thấy thông báo XÂY DỰNG THÀNH CÔNG và nếu bạn truy cập trang hồ sơ công khai DockerHub của mình, bạn sẽ thấy thông báo tương tự:
có nghĩa là hình ảnh Docker của chúng tôi với ứng dụng đang chờ triển khai tới máy AWS EC2. Nhưng đây là tài liệu cho một bài đăng trên blog khác :)
Tóm lược
Trong một vài bước, tôi đã mô tả cách thêm các khả năng của Docker vào dự án Java của bạn, cách định cấu hình hình ảnh của bạn và xuất bản nó trong DockerHub. Toàn bộ quá trình này không quá phức tạp và cho phép chúng tôi chuẩn bị ứng dụng để triển khai trên mọi máy hoặc máy chủ Linux hỗ trợ Docker.
Có thể bạn quan tâm
