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 postgresmật khẩu người dùng:

sudo passwd postgres

4.Đặt mật khẩu cho postgresngườ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à postgresngườ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.conftrong trình soạn thảo văn bản. Bỏ chú thích listen_addressesdò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 postgresqldị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.jsvà 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 pgmô-đ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 postgresmậ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 pgmô-đ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 databasemá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 docker0giao diện mạng. Sử dụng ifconfighoặ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.conftrong 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 databasemáy chủ, trỏ đến địa chỉ IP của máy chủ Docker. Khai báo máy databasechủ 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 databasemá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 postgreshình ảnh:

docker pull postgres

3.Đảm bảo rằng backup.sqltệp của bạn nằm trong thư mục làm việc hiện tại, sau đó chạy postgreshình ảnh:

docker run -d -v `pwd`:/backup/ --name pg_container postgres 

Tùy chọn này -vgắ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 --linktù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_containerdưới tên máy chủ database.

6.Mở /etc/hostsvà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ủ databasenhư 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 databasemá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 --linkor --hostmỗ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.ymltệ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.ymltệ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_containervà node_containertừ 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. linksMục nhập này có cùng chức năng như --linktùy chọn trong runlệ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.jstừ 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.ymltệ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: localhosttrên container sẽ trỏ đến localhosttrê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/