LỜI MỞ ĐẦUVới chủ đề “Tìm hiểu Docker và ứng dụng mình họa”nhóm chúng em chỉ thựchiện dưới dạng nghiên cứu và xây dựng các chức năng dựa vào việc tìm hiểu thực tế vànhững kiến thức được
Trang 1ĐẠI HỌC QUỐC GIA THÀNH PHỐ HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN
KHOA CÔNG NGHỆ PHẦN MỀM - o0o -
ĐỒ ÁN MÔN HỌC
ĐỒ ÁN 2
ĐỀ TÀI: Tìm hiểu Docker và ứng dụng minh họa
Giảng viên hướng dẫn:
Huỳnh Nguyễn Khắc Huy Sinh viên thực hiện:
Phạm Quang Nhân-17520122 Trần Ngọc Toàn-17521142
TP.HCM, 30/12/2020
Trang 2LỜI CẢM ƠN
Lời đầu tiên chúng em xin gửi lời cảm ơn chân thành tới giảng viên môn đồ án 2,thầy Huỳnh Nguyễn Khắc Huy đã tận tình giúp đỡ trong thời gian qua Vì thời gian vànăng lực còn có hạn chế nên không thể tránh khỏi những sai sót trong khi thực hiện đồ áncủa mình Rất mong được sự góp ý bổ sung của thầy để đề tài của em ngày càng hoànthiện hơn
Bên cạnh đó,chúng em cũng xin gửi lời cảm ơn chân thành đến tất cả các anh chị,các bạn trong và ngoài lớp đã kịp thời hỗ trợ, chia sẻ tài liệu và đưa ra những nhận xét,góp ý chân thành nhằm giúp đồ án được hoàn thiện hơn Đặc biệt là các anh chị K11trong khoa Công nghệ phần mềm đã nhiệt tình chia sẻ kinh nghiệm và giải đáp các thắcmắc
Chúng em xin chân thành cảm ơn!
Tp Hồ Chí Minh, tháng 12 năm 2020
Trang 3NHẬN XÉT CỦA GIẢNG VIÊN
Mục lục
Trang 4LỜI MỞ ĐẦU
Với chủ đề “Tìm hiểu Docker và ứng dụng mình họa”nhóm chúng em chỉ thựchiện dưới dạng nghiên cứu và xây dựng các chức năng dựa vào việc tìm hiểu thực tế vànhững kiến thức được học trên lớp, nhưng với những nghiên cứu dưới đây sẽ là nền tảng
để phát triển sâu rộng hơn cho những đồ án môn học sau này
Do là lần đầu tiên chúng em tiếp cận với công nghệ Docker Kèm với những sự hạn chế
ở khả năng cũng như kiến thức thực tế Xin thầy/cô thông cảm những sai xót của chúng em.
Trang 5I. Giới thiệu đề tài
1. Lý do chọn đề tài
Trong bối cảnh phát triển phần mềm ngày nay, các lập trình viên đang không chỉ phảilàm tốt ở khía cạnh lập trình, mà còn phải đưa sản phẩm đến tay người tiêu dùng Khókhăn ở chỗ khi lập trình, các lập trình viên sử dụng môi trường khác với môi trường sảnphẩm Việc setup môi trường ban đầu đã phức tạp, làm lại công việc đó sau khi sản phẩm
đã thành hình còn khó hơn do có thể gặp các lỗi không tương thích khác nhau Từ đó màDocker đã ra đời để giải quyết bài toán trên
Nhận thấy được nhu cầu trên cùng với qua tìm hiểu, chúng em xin phép thực hiện đề
tài “Tìm hiểu Docker và ứng dụng minh họa”.
II. Giới thiệu về docker
1 Docker là gì
Docker là nền tảng cung cấp cho các công cụ, service để các developers, adminsystems
có thể phát triển, thực thi, chạy các ứng dụng với containers Hay nói một cách khác nó làmột nền tảng để cung cấp cách để building, deploy và run các ứng dụng một cách dễ dàng trên nền tảng ảo hóa - "Build once, run anywhere" Hay nói một cách dễ hiểu như sau: Khi chúng ta muốn chạy app thì chúng ta phải thiết lập môi trường chạy cho nó Thay vì chúng ta sẽ đi cài môi trường chạy cho nó thì chúng ta sẽ chạy docker
Ứng dụng Docker chạy trong vùng chứa (container) có thể được sử dụng trên bất kỳ hệ thống nào: máy tính xách tay của nhà phát triển, hệ thống trên cơ sở hoặc trong hệ thống đám mây Và là một công cụ tạo môi trường được "đóng gói" (còn gọi là Container) trên máy tính mà không làm tác động tới môi trường hiện tại của máy, môi trường trong Docker sẽ chạy độc lập
Docker có thể làm việc trên nhiều nền tảng như Linux, Microsoft Windows và Apple OS X
Docker mang lại lợi ích cho cả SysAdmin, Developer (Dev) lẫn Devops Đối với Dev, họ không cần phải biết nhiều về việc vận hành các chương trình, phần mềm phía dưới Ngoài ra Dev cũng tận dụng được hàng nghìn các chương trình được đóng gói sẵn và
Trang 6chia sẻ trên mạng Đối với SysAd, Docker mang đến sự linh hoạt trong quản lý, tăng khả năng tận dụng tài nguyên hệ thống Đối với Devops, lợi ích chính là tận dụng cả hai lợi ích ở trên.
Ưu điểm :
• Kích hoạt nhiều hệ điều hành trên cùng một máy
• Nó rẻ hơn so với các phương pháp trước đây, do thiết lập cơ sở hạ tầng ít hơn / nhỏ gọn
• Nếu có bất kỳ trạng thái thất bại nào, thật dễ dàng để phục hồi và bảo trì
• Cung cấp nhanh hơn các ứng dụng và tài nguyên cần thiết cho các nhiệm vụ
• Tăng năng suất, hiệu quả và đáp ứng CNTT
• Sử dụng ít tài nguyên: Thay vì phải ảo hóa toàn bộ hệ điều hành thì chỉ cần build
và chạy các container độc lập sử dụng chung kernel duy nhất
• Tính đóng gói và di động: Tất cả các gói dependencies cần thiết đều được đóng gói vừa đủ trong container Và sau đó có thể mang đi triển khai trên các server khác
• Cô lập tài nguyên: server bố không biết ở trong container chạy gì và container cũng không cần biết bố nó là CentOs hay Ubuntu Các container độc lập với nhau
và có thể giao tiếp với nhau bằng một interface
• Hỗ trợ phát triển và quản lý ứng dụng nhanh: Đối với Dev, sử dụng docker giúp họgiảm thiểu thời gian setup môi trường, đóng gói được các môi trường giống nhau
từ Dev - Staging - Production
• Mã nguồn mở: Cộng đồng support lớn, các tính năng mới được release liên tục
Trang 7Từ kiến trúc VM ở trên, chúng ta có thể hình dung ra rằng 3 hệ điều hành Guest hoạt động như các máy ảo đang chạy trên một hệ điều hành máy chủ Trong Virtualization, quá trình cấu hình lại phần cứng, phần sụn thủ công, cài đặt HĐH mới, cài đặt hệ điều hành mới có thể hoàn toàn tự động, tất cả các bước này được lưu trữ dưới dạng dữ liệu trong bất kỳ tệp nào của đĩa.
Trong Virtualization, mỗi ứng dụng và hệ điều hành sống trong một thùng chứa phần mềm riêng biệt có tên Virtural Machine (VM) , trong đó VM hoàn toàn tách biệt, tất cả các tài nguyên điện toán như CPU, lưu trữ và kết nối mạng được gộp chung với nhau Virtural Machine (VM) về bản chất là một giả lập của một máy tính để thực thi các ứng dụng giống như một máy tính thật VMs chạy trên một máy vật lý sử dụng một thứ gọi là
“hypervisor” Hypervisor có thể là phần cứng, phần mềm hoặc là một bản firmware nào
đó có thể chạy trực tiếp trên máy thật (host machine) có chức năng cho nhiều máy ảo chạy trên nó Host machine sẽ cung cấp cho VMs những tài nguyên như là RAM, CPU Những tài nguyên đó sẽ được phân bổ giữa các VMs theo cách mà bạn cho là hợp lý Nếumột VM chạy nhiều ứng dụng hoặc nặng thì bạn phải cung cấp tài nguyên cho nó nhiều tài nguyên hơn những VMs khác trên cùng một host machine
Trang 8Những VMs chạy trên host machine thường được gọi là guest machine Guest machine này sẽ chứa tất cả những thứ mà hệ thống cần để chạy ứng dụng như hệ điều hành (OS), system binaries và libraries VMs chạy trên hệ điều hành của host machine và không thể truy cập trực tiếp đến phần cứng mà phải thông qua hệ điều hành.
Để khắc phục những hạn chế trên của Virtualization, Containerization ra đời
3 Containerization là gì ?
Containerization là một kỹ thuật trong đó virtualization được đưa containerization lên mức hệ điều hành Trong containerization, ta virtualization tài nguyên hệ điều hành, sẽ hiệu quả hơn vì không có hệ điều hành khách nào tiêu thụ tài nguyên máy chủ, vì
container chỉ sử dụng hệ điều hành của máy chủ và chỉ chia sẻ thư viện & tài nguyên có liên quan khi được yêu cầu Các nhị phân và thư viện cần thiết của container chạy trên kernel host dẫn đến việc xử lý và thực thi nhanh hơn
Trang 9Dựa vào sơ đồ bên trên Các bạn có thể thấy các gói container chỉ là một user space bao gồm ứng dụng, system binaries và libraries mà không cần guest OS hoặc ảo hóa phần cứng như VMs Đây là cái mà làm cho các container nhẹ hơn (lightweight) Các container
sẽ chạy trên công nghệ cụ thể ở đây là Docker Engine
Ưu điểm :
• Các container nhỏ và nhẹ hơn vì chúng có chung nhân hệ điều hành
• Không mất nhiều thời gian để khởi động (trong một vài giây)
• Hiệu suất cao với việc sử dụng tài nguyên thấp hơn
4 Sự khác biệt giữa Docker và Virtual Machine
• Docker : Dùng chung kernel, chạy độc lập trên Host Operating System và có thể
chạy trên bất kì hệ điều hành nào cũng như cloud Khởi động và làm cho ứng dụngsẵn sàng chạy trong 500ms, mang lại tính khả thi cao cho những dự án cần sự mở rộng nhanh
• Virtual Machine : Cần thêm một Guest OS cho nên sẽ tốn tài nguyên hơn và làm
chậm máy thật khi sử dụng Thời gian khởi động trung bình là 20s có thể lên đến hàng phút, thay đổi phụ thuộc vào tốc độ của ổ đĩa
5 Các điểm hạn chế của Docker
Docker không phải là hoàn hảo
Docker base trên Linux 64bit và các tính năng cgroup, namespaces Vì thế Linux 32bit hoặc môi trường Window không thể chạy được docker (đối với phiên bản CE)
Sử dụng container tức là bạn sử dụng chung kernel của hệ điều hành Trong trường hợp bạn download image có sẵn và trong đó có một số công cụ có thể kiểm soát được kernel thì server của bạn có thể bị mất kiểm soát hoàn toàn
Các tiến trình chạy container một khi bị stop thì sẽ mất hoàn toàn dữ liệu nếu không đượcmount hoặc backup Điều này có thể sẽ gây ra một số bất tiện…
Tuy nhiên Docker nói riêng hay Containerlization nói chung vẫn sẽ là tương lai và là xu hướng chung của hầu hết các doanh nghiệp trên toàn thế giới
Trang 10Tại sao nên dùng Docker?
• Tiện lợi: Khi bạn được phân bổ vào dự án mới, bạn đọc file README, thấy dự án
hiện tại cần cài rất nhiều thứ, nào là ruby, rồi rails, redis, mysql, nginx, mỗi thứ lại phải kèm theo version bao nhiêu, Bạn lên google search cách cài đặt, config những thứ này sẽ mất một khoảng thời gian khá lâu Chưa hết, có thể chưa cài xong đã conflic tùm lum, cái nọ xung đột cái kia chẳng hạn, lại còn ảnh hưởng tới những chương trình cũ đã cài đặt trong máy nữa chứ, thôi cài lại luôn cả hệ điều hành cho máy Thế là mất thời gian, mệt mỏi với nhưng thao tác phụ mà chưa tập trung được vào việc chính Nhưng với docker mọi thứ đơn gian hơn nhiều, chỉ vài dòng lệnh thôi, bạn sẽ có thể nhanh chóng tạo được môi trường ảo hóa chứa đầy
đủ những cài đặt cần thiết cho project rồi
• Dễ dàng sử dụng: Docker rất dễ cho mọi người sử dụng từ developers, systems
admins, architects…v…v nó tận dụng lợi thế của container để build, test nhanh chóng Có thể đóng gói ứng dụng trên laptop của họ và chạy trên public cloud, private cloud v.v… “Build once, run anywhere”
• Tốc độ: Docker container rất nhẹ và nhanh, bạn có thể tạo và chạy docker
container trong vài giây so sánh với VMs thì mỗi lần chạy VMs cần rất nhiều thời gian khởi động
• Khả năng di động: môi trường develop được dựng lên bằng docker có thể chuyển
từ người này sang người khác mà không làm thay đổi cấu hình ở trong
• Chia sẻ: DockerHub là một “app store for docker images” Trên DockerHub có
hàng ngàn public images được tạo bởi cộng đồng Dễ dàng tìm thấy những image
mà bạn cần và chỉ cần pull về và sử dụng với một số sửa đổi nhỏ
• Môi trường chạy và khả năng mở rộng: Bạn có thể chia nhỏ những chức năng
của ứng dụng thành các container riêng lẻ Ví dụng Database chạy trên một
Trang 11container và Redis cache có thể chạy trên một container khác trong khi ứng dụng Node.js lại chạy trên một cái khác nữa Với Docker, rất dễ để liên kết các
container với nhau để tạo thành một ứng dụng, làm cho nó dễ dàng scale, update các thành phần độc lập với nhau
Khi nào sử dụng Docker?
• Khi bạn cần triển khai kiến trúc Mircoservices
• Khi ứng dụng bạn cần scale một cách linh hoạt
• Khi bạn cần build 1 lần và chạy ở nhiều máy khác nhau mà không cần quan tâm đến config
• Khi bạn cần một cách tiếp cận mới về building, shipping, running ứng dụng một cách nhanh chóng dễ dàng
III. Các thành phần cơ bản và kiến trúc của Docker
1 Các thành phần cơ bản của Docker
Docker Engine
Docker engine là một ứng dụng client-server có 2 phiên bản phổ biến:
• Docker Community Edition (CE): Là phiên bản miễn phí và chủ yếu dựa vào
các sản phầm nguồn mở khác
Trang 12• Docker Enterprise(EE): Khi sử dụng phiên bản này bạn sẽ nhận được sự support
của nhà phát hành, có thêm các tính năng quản lý và security
Các thành phần chính của docker engine gồm có:
• Server hay còn được gọi là docker daemon: chịu trách nhiệm tạo, quản lý các Docker objects như images, containers, networks, volume
• REST API: docker daemon cung cấp các api cho Client sử dụng để thao tác với Docker
• Client là thành phần đầu cuối cung cấp một tập hợp các câu lệnh sử dụng api để người dùng thao tác với Docker
Orchestration tools
Docker Machine : Machine tạo Docker Engine trên laptop của bạn hoặc trên bất cứ dịch
vụ cloud phổ biến nào như AWS, Azure, Google Cloud, Softlayer hoặc trên hệ thống datacenter như VMware, OpenStack Docker Machine sẽ tạo các máy ảo và cài Docker Engine lên chúng và cuối cùng nó sẽ cấu hình Docker Client để giao tiếp với Docker Engine một cách bảo mật
Docker Compose : là công cụ giúp định nghĩa và khởi chạy multi-container Docker
applications
Docker Swarm : là một công cụ giúp chúng ta tạo ra một clustering Docker Nó giúp
chúng ta gom nhiều Docker Engine lại với nhau và ta có thể "nhìn" nó như duy nhất một virtual Docker Engine
Một số thành phần khác
Dockerfile : như một script dùng để build các image trong container Dockerfile bao gồm
các câu lệnh liên tiếp nhau được thực hiện tự động trên một image gốc để tạo ra một image mới Dockerfile giúp đơn giản hóa tiến trình từ lúc bắt đầu đến khi kết thúc
Docker Toolbox : Bởi vì Docker Engine dùng một số feature của kernel Linux nên ta sẽ
không thể chạy Docker Engine natively trên Windows hoặc BSD được Ở các phiên bản trước đây thì ta sẽ cần một máy ảo cài một phiên bản Linux nào đó và sau đó cài Docker Engine lên máy ảo đó
Trang 132 Kiến trúc của Docker.
Docker Daemon: lắng nghe các yêu cầu từ Docker Client để quản lý các đối tượng như
Container, Image, Network và Volumes Các Docker Daemon cũng giao tiếp với nhau để quản lý các Docker Service
Docker Client: là một công cụ giúp người dùng giao tiếp với Docker host Khi người
dùng gõ lệnh docker run imageABC tức là người dùng sử dụng CLI và gửi request đến dockerd thông qua api, và sau đó Docker daemon sẽ xử lý tiếp Docker client có thể giao tiếp và gửi request đến nhiều Docker daemon
Docker Registry (Docker Hub): là một kho chứa các image được publish bởi cộng đồng
Docker Nó giống như GitHub và bạn có thể tìm những image cần thiết và pull về sử dụng
Docker object: chính là các đối tượng mà ta thường xuyên gặp khi sử dụng Docker Gồm
có Images và Containers
• Images: hiểu nôm na là một khuôn mẫu để tạo một container Thường thì image sẽ
base trên 1 image khác với những tùy chỉnh thêm ví dụ bạn build 1 image dựa trên image ubuntu để chạy Apache web service và ứng dụng của bạn và những tùy chỉnh, cấu hình để ứng dụng của bạn có thể chạy được Bạn có thể tự build một image riêng cho mình hoặc sử dụng những image được publish từ cộng đồng Docker Hub Một image sẽ được build dựa trên những chỉ dẫn của Dockerfile
Trang 14• Containers: là một instance của một image Bạn có thể create, start, stop, move or
delete container dựa trên Docker API hoặc Docker CLI
⭐ Sự khác biệt giữa Docker Images và Docker Containers
• Docker Images: Là một template chỉ cho phép đọc, ví dụ một image có thể chứa
hệ điều hành Ubuntu và web app Images được dùng để tạo Docker container Docker cho phép chúng ta build và cập nhật các image có sẵn một cách cơ bản nhất, hoặc bạn có thể download Docker images của người khác
• Docker Containers: Docker container có nét giống với các directory Một Docker
container giữ mọi thứ chúng ta cần để chạy một app Mỗi container được tạo từ Docker image Docker container có thể có các trạng thái run, started, stopped, moved và deleted
3 Quy trình thực thi của một hệ thống sử dụng Docker
Như trong hình, một hệ thống Docker được thực thi với 3 bước chính :
BUILD -> PUSH -> PULL,RUN
Build: Đầu tiên tạo một dockerfile, trong dockerfile này chính là code của chúng ta
Dockerfile này sẽ được Build tại một máy tính đã cài đặt Docker Engine Sau khi build ta
sẽ có được Container, trong Container này chứa ứng dụng kèm bộ thư viện của chúng ta
Push: Sau khi có được Container, chúng ta thực hiện push Container này lên cloud và lưu
tại đó
Trang 15Pull, Run: Nếu một máy tính khác muốn sử dụng Container chúng ta thì bắt buộc máy
phải thực hiện việc Pull container này về máy, tất nhiên máy này cũng phải cài Docker Engine Sau đó thực hiện Run Container này
4 Tạo image từ Docker
i Cấu trúc một Dockerfile
• Dockerfile là một file dạng text không có extension, và tên bắt buộc phải là Dockerfile
• Dockerfile là một file kịch bản sử dụng để tạo mới một image
ii Cấu trúc một Dockerfile
Đây là cấu trúc một Dockerfile của ứng dụng Wordpress
Trang 16iii Các command cơ bản trong Dockerfile FROM
FROM centos:centos7
FROM chỉ định rằng image build này sẽ base trên image gốc nào
Trang 17RUN yum update –y
RUN thực hiện một câu lệnh Linux Tùy vào image gốc mà có các câu lệnh tương ứng (ví
dụ Ubuntu sẽ là RUN apt-get update -y)
COPY
COPY start.sh /start.sh
COPY Copy một file từ Dockerhost vào image trong quá trình build image
ENV
ENV source /var/www/html/
COPY index.html ${source}
ENV là biến môi trường sử dụng trong quá trình build image
ENV chỉ có thể được sử dụng trong các command sau:
Trang 18EXPOSE Chỉ định các port sẽ Listen trong container khi khởi chạy container từ image
IV. Áp dụng docker vào project thực tế
Áp dụng docker vào đồ án “Phần mềm quản lý khám chữa bệnh”
Cấu trúc của project gồm 3 phần:
• BACK-END: APIs, sử dụng ngôn ngữ nodejs
• FRONT-END: sử dụng Reactjs
• DATABASE: MONGODB, lưu trữ dữ liệu trên mây với MongoDb Atlas
Vậy chỉ còn 2 phẩn BE và FE cần được đưa vào docker
1 Docker cho back-end
Docker file
Trang 19From: pull image node version 15.2.0
Workdir: chỉ thị folder làm việc của project trong docker
Copy 1: copy tất cả những file có dạng packge….json vào thư mục workdir
Run: thực hiện việc install nodemodules từ fike package.json
Copy 2: copy tất cả những file cùng cấp dockerfile trong thư mục hiện tại
Expose: mở port 3000 cho docker container
Cmd: câu lệnh sẽ thực thi khi khởi chạy container, ở đây là khởi chạy project nodejs
Trang 202 Docker cho front-end
Do Nodejs và Reactjs cùng phát triển với chung một ngôn ngữ lập trình và môi trường nên dockerfile khá giống nhau
Mở rộng với NGINX server:
Như đã biết, Nginx có nhiều ưu điểm như config url, tối ưu hóa bộ nhớ, Reverse proxy với bộ nhớ đệm, Cân bằng tải (load balancing), …
Trang 21Thay vì chỉ chạy project bằng npm start thông thường, ta sửa thành build để tạo bản rút gọn để đưa vào nginx server như khi làm trên local
Copy bản đã build vào nginx server, copy đè file config mặc định của nginx bằng file bêndưới, với
- Location / : phần đầu chỉ định nơi để lấy giao diện trả về cho người dùng với uri tương úng
- Location /api: setup proxy để nginx chấp thuận việc gửi nhận dữ liệu đến một app khác, ví dụ ở đây là một server backend
Trang 223 Build và khởi chạy container
Mở terminal ở thư mục có chứa docker file và chạy dòng lệnh:
docker buid –t <name>
với –t <name> để đặt tên cho container, “-t” là “tag”
“.” Là đường dẫn tới thư mục chứ docker file, do mở sẳn terminal ở nơi chứa dockerfile nên đường dẫn là thư mục hiện tại “.”
Lệnh “docker images” dùng để liệt kê toàn bộ danh sách những images có trên máy.Tiến hành khởi chạy container thông qua image
Câu lệnh khởi chạy là:
Docker run –p <local port>:<docker port> <image’s name>
-p(port): bến phải là port trong container, 3001:3001 nghĩa là port 3001 trong docker được nối với 3001 ở localhost
Trang 23Kiểm tra với POSTMAN api đăng nhập thu được kết quả success,…
Để dừng container, ta sử dụng lệnh “docker ps” để liệt kê những container đang chạy
Và “docker container stop <cotainer’s id>” để dừng
Thử đổi port và kiểm tra lại
Trang 24Port 3001 trong container đã được bind sang 8080 ở localhost nên khi gọi đến 3001 sẽ không trả và được kết quả
Trang 25Còn với 8080 thì được
Trang 264 Docker-Compose
Để thuận tiện cho việc phát triển, sử dụng docker-compose để khi bắt đầu lập trình chỉ cần khởi chạy docker-compose 1 lần để start cả 2 container
Có 2 service là “backend” và “frontend”
Container_name: đặt tên cho container
Restart: cài đặt chế độ khởi đông lại container, ở đây chỉ restart khi stop
Trang 27Buid context: đường dẫn tới docker file của container đó
Volumes: mount file từ trong docker container ra ngoài máy mình, để khi sửa code -> code trong docker container cũng được thay đổi
Port: bến phải là port trong container, 3001:3001 nghĩa là port 3001 trong docker được nối với 3001 ở localhost
Networks: cho 2 container vào cùng 1 mạng lưới
Lưu ý khi phát triển liên kết giữa 2 platform khác nhau, cần phải cài đặt proxy, để cho phép bên này gọi tới bên kìa Như FE phải sử dụng API ở BE, nên cần thiết lập proxy ở FE
Nếu sử dụng docker-compose, khi setup proxy ta sử dụng tên container thay cho