Khi sử dụng Docker để chứa các ứng dụng của bạn, thông lệ chung là chạy từng thành phần của ứng dụng trong một vùng chứa riêng biệt. Ví dụ: một trang web có thể có máy chủ web, ứng dụng và cơ sở dữ liệu, mỗi thành phần chạy trong vùng chứa riêng của nó.
Cấu hình các container để giao tiếp với nhau và máy chủ có thể là một thách thức. Hướng dẫn này sẽ sử dụng một ứng dụng ví dụ đơn giản để chứng minh những điều cơ bản về giao tiếp container Docker. Ứng dụng sẽ bao gồm một ứng dụng Node.js đọc dữ liệu từ cơ sở dữ liệu PostgreSQL.
Trước khi bạn bắt đầu
Cài đặt Docker CE
Bạn sẽ cần một Linode đã cài đặt Docker CE để làm theo các bước trong hướng dẫn này.
Để cài đặt Docker CE (Phiên bản cộng đồng), hãy làm theo hướng dẫn trong một trong các hướng dẫn dưới đây:
Để xem hướng dẫn cài đặt cho các bản phân phối Linux hoặc hệ điều hành khác như Mac hoặc Windows, hãy tham khảo tài liệu chính thức của Docker tại đây: Cài đặt Docker Engine
Ví dụ về ứng dụng Node.js
Ứng dụng ví dụ được sử dụng trong hướng dẫn này sẽ là một ứng dụng Node.js đơn giản sẽ đọc “Hello world” từ cơ sở dữ liệu PostgreSQL và in ra bảng điều khiển. Trong phần này, bạn sẽ xây dựng và kiểm tra ứng dụng trên Linode của mình mà không sử dụng container.
Cài đặt và cấu hình PostgreSQL
1.Cập nhật hệ thống của bạn:
sudo apt update && sudo apt upgrade
2.Cài đặt PostGreSQL:
sudo apt install postgresql postgresql-contrib
3.Thay đổi postgres
mật khẩu người dùng:
sudo passwd postgres
4.Đặt mật khẩu cho postgres
người dùng cơ sở dữ liệu:
su - postgres
psql -d template1 -c "ALTER USER postgres WITH PASSWORD 'newpassword';"
5.Tạo cơ sở dữ liệu cho ứng dụng ví dụ và kết nối với nó:
createdb nodejs
psql nodejs
6.Thêm “Hello world” vào cơ sở dữ liệu:
nodejs=# CREATE TABLE hello (message varchar);
nodejs=# INSERT INTO hello VALUES ('Hello world');
nodejs=# \q
7.Tạo bản sao lưu cơ sở dữ liệu để sử dụng sau:
pg_dumpall > backup.sql
8.Đăng xuất với tư cách là postgres
người dùng Linux:
exit
9.Sao chép dữ liệu dump vào thư mục gốc của bạn:
sudo cp /var/lib/postgresql/backup.sql ~/.
10.Vì bạn sẽ kết nối đến cơ sở dữ liệu này từ một container (sẽ có địa chỉ IP khác locahost
), bạn sẽ cần chỉnh sửa tệp cấu hình PostgreSQL để cho phép kết nối từ các địa chỉ từ xa. Mở /etc/postgresql/9.5/main/postgresql.conf
trong trình soạn thảo văn bản. Bỏ chú thích listen_addresses
dòng và đặt thành ‘*’:
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------
# - Connection Settings -
listen_addresses = '*' # what IP address(es) to listen on;
11.Kích hoạt và khởi động postgresql
dịch vụ:
sudo systemctl enable postgresql
sudo systemctl start postgresql
Tạo ứng dụng Hello World
1.Cài đặt Node và NPM:
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install nodejs
2.Điều hướng đến thư mục chính và tạo một thư mục:
cd
mkdir app && cd app
3.Sử dụng trình soạn thảo văn bản, tạo app.js
và thêm nội dung sau:
const { Client } = require('pg')
const client = new Client({
user: 'postgres',
host: 'localhost',
database: 'nodejs',
password: 'newpassword',
port: 5432
})
client.connect()
client.query('SELECT * FROM hello', (err, res) => {
console.log(res.rows[0].message)
client.end()
})
Ứng dụng này sử dụng pg
mô-đun NPM (node-postgres) để kết nối với cơ sở dữ liệu được tạo trong phần trước. Sau đó, nó truy vấn bảng ‘hello’ (trả về thông báo “Hello world”) và ghi lại phản hồi vào bảng điều khiển. Thay thế 'newpassword'
bằng postgres
mật khẩu người dùng cơ sở dữ liệu mà bạn đã đặt trong phần trước.
Ghi chú: Mô pg
-đun cũng có thể sử dụng các biến môi trường để cấu hình kết nối máy khách. Đây là tùy chọn được khuyến nghị cho các ứng dụng sản xuất. Đọc thêm về các biến môi trường trong tài liệu node-postgres .
4.Cài đặt pg
mô-đun:
npm install pg
5.Kiểm tra ứng dụng:
node app.js
Nếu cơ sở dữ liệu được cấu hình đúng, “Hello world” sẽ hiển thị trên bảng điều khiển.
Kết nối Container với Docker Host
Phần này minh họa trường hợp sử dụng trong đó ứng dụng Node.js được chạy từ vùng chứa Docker và kết nối với cơ sở dữ liệu đang chạy trên máy chủ Docker.
Thiết lập Docker Container
1.Trở về thư mục gốc của bạn:
cd
2.Tạo Dockerfile để chạy ứng dụng Node.js:
FROM debian
RUN apt update -y && apt install -y gnupg curl
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && apt install -y nodejs
COPY app/ /home/
ENTRYPOINT tail -F /dev/null
3.Hình ảnh được xây dựng từ Dockerfile này sẽ sao chép app/
thư mục vào hình ảnh mới. Chỉnh sửa app.js
để cho phép ứng dụng kết nối với database
máy chủ thay vì localhost
:
const client = new Client({
user: 'postgres',
host: 'database',
database: 'nodejs',
password: 'newpassword',
port: 5432
})
4.Xây dựng một hình ảnh từ Dockerfile:
docker build -t node_image .
Kết nối Container với Cơ sở dữ liệu
1.Docker tự động thiết lập mạng cầu nối mặc định , được truy cập thông qua docker0
giao diện mạng. Sử dụng ifconfig
hoặc ip
để xem giao diện này:
ifconfig docker0
Đầu ra sẽ giống như sau:
docker0 Link encap:Ethernet HWaddr 02:42:1e:e8:39:54
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:1eff:fee8:3954/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3848 errors:0 dropped:0 overruns:0 frame:0
TX packets:5084 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:246416 (246.4 KB) TX bytes:94809688 (94.8 MB)
Địa chỉ IP nội bộ của máy chủ Docker (Linode của bạn) là 172.17.0.1.
2.Cho phép PostgreSQL chấp nhận kết nối từ giao diện Docker. Mở /etc/postgresql/9.5/main/pg_hba.conf
trong trình soạn thảo văn bản và thêm dòng sau:
host all postgres 172.17.0.0/16 password
Vì 172.17.0.1 là IP của máy chủ Docker nên tất cả các container trên máy chủ sẽ có địa chỉ IP trong phạm vi 172.17.0.0/16.
3.Khởi động lại cơ sở dữ liệu:
sudo systemctl restart postgresql
4.Bắt đầu container:
docker run -d --add-host=database:172.17.0.1 --name node_container node_image
Tùy chọn này --add-host
định nghĩa một database
máy chủ, trỏ đến địa chỉ IP của máy chủ Docker. Khai báo máy database
chủ khi chạy, thay vì mã hóa cứng địa chỉ IP trong ứng dụng, giúp giữ cho vùng chứa có thể tái sử dụng.
5.Từ bên trong vùng chứa, sử dụng ping
để kiểm tra kết nối với database
máy chủ:
docker exec -it node_container ping database
6.Mỗi container Docker cũng được gán địa chỉ IP riêng từ bên trong khối 172.17.0.0/16. Tìm địa chỉ IP của container này bằng ip
:
docker exec -it node_container ip addr show eth0
Bạn có thể kiểm tra kết nối này bằng cách ping địa chỉ này từ máy chủ Docker.
7.Chạy ứng dụng:
docker exec -it node_container node home/app.js
Nếu cấu hình thành công, chương trình sẽ hiển thị đầu ra bảng điều khiển “Hello world” như trước.
Kết nối hai container
Trong phần này, cả ứng dụng và cơ sở dữ liệu sẽ chạy trong các container riêng biệt. Bạn có thể sử dụng hình ảnh postgres chính thức từ Docker Hub và tải bản dump SQL đã tạo trước đó.
Quan trọng: Bạn không nên lưu trữ dữ liệu cơ sở dữ liệu sản xuất bên trong một container Docker. Container phải được coi là các thực thể tạm thời: nếu một container bất ngờ bị sập hoặc được khởi động lại, tất cả dữ liệu trong cơ sở dữ liệu sẽ bị mất.
1.Dừng và xóa vùng chứa Node.js:
docker stop node_container
docker rm node_container
2.Kéo postgres
hình ảnh:
docker pull postgres
3.Đảm bảo rằng backup.sql
tệp của bạn nằm trong thư mục làm việc hiện tại, sau đó chạy postgres
hình ảnh:
docker run -d -v `pwd`:/backup/ --name pg_container postgres
Tùy chọn này -v
gắn thư mục làm việc hiện tại của bạn vào /backup/
thư mục trên vùng chứa mới.
4.Container mới sẽ tự động khởi động cơ sở dữ liệu postgres và tạo người dùng postgres. Nhập container và tải bản dump SQL:
docker exec -it pg_container bash
cd backup
psql -U postgres -f backup.sql postgres
exit
5.Chạy lại hình ảnh nút. Lần này, thay vì --add-host
, hãy sử dụng --link
tùy chọn để kết nối vùng chứa với pg_container
:
docker run -d --name node_container --link=pg_container:database node_image
Thao tác này sẽ liên kết pg_container
dưới tên máy chủ database
.
6.Mở /etc/hosts
vào node_container
để xác nhận liên kết đã được tạo:
docker exec -it node_container cat /etc/hosts
Sẽ có một dòng tương tự như sau:
172.17.0.2 database pg_container
Điều này cho thấy pg_container
địa chỉ IP 172.17.0.2 đã được gán và được liên kết đến vùng chứa này thông qua tên máy chủ database
như mong đợi.
7.Vì ứng dụng Node.js vẫn đang mong đợi kết nối với cơ sở dữ liệu PostgreSQL trên database
máy chủ nên không cần thay đổi thêm nữa. Bạn sẽ có thể chạy ứng dụng như trước:
docker exec -it node_container node home/app.js
Sử dụng Docker Compose
Sử dụng tùy chọn --link
or --host
mỗi lần bạn khởi chạy container có thể rất cồng kềnh. Nếu máy chủ hoặc bất kỳ container nào của bạn bị sập, chúng phải được kết nối lại thủ công. Đây không phải là tình huống lý tưởng cho bất kỳ ứng dụng nào yêu cầu khả năng sẵn sàng liên tục. May mắn thay, Docker cung cấp Docker Compose để quản lý nhiều container và tự động liên kết chúng với nhau khi chúng được khởi chạy. Phần này sẽ sử dụng Docker Compose để tái tạo kết quả của phần trước.
Ghi chú: Để biết giải thích toàn diện hơn về Docker Compose và cách viết docker-compose.yml
tệp cấu hình, hãy xem hướng dẫn Docker Compose đầy đủ của chúng tôi .
1.Cài đặt Docker Compose:
sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
2.Trong cùng thư mục với Dockerfile của bạn, hãy tạo một docker-compose.yml
tệp có nội dung sau:
version: '3'
services:
database:
image: postgres
container_name: pg_container
volumes:
- pgdata:/var/lib/postgresql/data
app:
build: .
container_name: node_container
links:
- database
environment:
- PGPASSWORD=newpassword
- PGUSER=postgres
- PGDATABASE=nodejs
- PGHOST=database
- PGPORT=5432
depends_on:
- database
volumes:
pgdata: {}
Khi bạn chạy Docker Compose với tệp này, nó sẽ tạo pg_container
và node_container
từ phần trước. Như trước, vùng chứa cơ sở dữ liệu sẽ sử dụng hình ảnh PostgreSQL chính thức, trong khi vùng chứa ứng dụng sẽ được xây dựng từ Dockerfile của bạn. links
Mục nhập này có cùng chức năng như --link
tùy chọn trong run
lệnh đã sử dụng trước đó.
3.Docker Compose cũng cho phép bạn thiết lập các giá trị môi trường, do đó bạn có thể đơn giản hóa ứng dụng để sử dụng các giá trị này thay vì phải mã hóa cứng các giá trị. Chỉnh sửa app.js
để xóa các giá trị này:
const express = require('express')
const { Client } = require('pg')
const client = new Client()
client.connect()
client.query('SELECT * FROM hello', (err, res) => {
console.log(res.rows[0].message)
client.end()
})
4.Xóa các thùng chứa trước đó:
docker rm -f node_container pg_container
5.Sử dụng Docker Compose để đưa các container lên:
docker-compose up -d
6.Tải dữ liệu ví dụ vào vùng chứa mới:
docker cp backup.sql pg_container:/
docker exec -it pg_container psql -U postgres -f backup.sql postgres
7.Chạy app.js
từ vùng chứa ứng dụng:
docker exec -it node_container node home/app.js
Ứng dụng sẽ chạy như trước.
Phần kết luận
Theo mặc định, Docker tự động gán một địa chỉ IP cho mỗi container và cho máy chủ Docker. Bạn có thể kết nối thủ công các dịch vụ giữa các container bằng cách sử dụng các địa chỉ này (giả sử tường lửa của bạn cho phép kết nối).
Tuy nhiên, Docker cũng cung cấp một số wrapper tiện lợi xung quanh các kết nối này để giúp bạn tăng tốc và đơn giản hóa quá trình kết nối. Bạn có thể kết nối máy chủ Docker của mình với một container có tên máy chủ duy nhất hoặc liên kết trực tiếp hai container. Sử dụng Docker Compose có thể đơn giản hóa quá trình này hơn nữa bằng cách cho phép bạn khai báo các kết nối trong docker-compose.yml
tệp để chúng được thiết lập tự động khi các container được đưa lên.
Có những tùy chọn kết nối khác không được đề cập trong hướng dẫn này. Ví dụ, bạn có thể chạy một container bằng cách sử dụng --net="host"
, sẽ chia sẻ ngăn xếp mạng của container đó với máy chủ Docker: localhost
trên container sẽ trỏ đến localhost
trên máy chủ Docker. Bạn cũng có thể hiển thị các cổng trên mỗi container Docker hoặc cấu hình mạng cầu nối mặc định để linh hoạt hơn. Để thảo luận sâu hơn về các tùy chọn này, hãy xem các liên kết trong phần Thông tin thêm bên dưới.
Thông tin thêm
Bạn có thể muốn tham khảo các nguồn sau để biết thêm thông tin về chủ đề này. Mặc dù chúng tôi cung cấp với hy vọng rằng chúng sẽ hữu ích, nhưng xin lưu ý rằng chúng tôi không thể đảm bảo tính chính xác hoặc tính kịp thời của các tài liệu được lưu trữ bên ngoài.
Nguồn: https://www.linode.com/docs/guides/docker-container-communication/