Làm thế nào chạy nhiều ứng dụng sử dụng Docker
Tôi có một ứng dụng rất đơn giản Node.js các truy cập được lưu trữ trên Redis. Tôi muốn chạy Redis và các node ứng dụng độc lập với nhau. Ở trong bài viết này, chúng ta sẽ tạo ra một ứng dụng Node.js đơn giản đó sẽ chạy trên ba container Docker Node. Các yêu cầu HTTP sẽ phân phối cho các nút ...
Tôi có một ứng dụng rất đơn giản Node.js các truy cập được lưu trữ trên Redis. Tôi muốn chạy Redis và các node ứng dụng độc lập với nhau. Ở trong bài viết này, chúng ta sẽ tạo ra một ứng dụng Node.js đơn giản đó sẽ chạy trên ba container Docker Node. Các yêu cầu HTTP sẽ phân phối cho các nút Node.js bởi một máy chủ Nginx chạy trên một container Docker phía trước các node cho cân bằng tải các node.
Vậy ta sẽ cần phải có các container như sau :
-
1 container Redis
-
3 container Node
-
1 container Nginx
Như thế ta sẽ có bức tranh tổng thể dưới đây:
Tôi có thể xây dựng các container từ đầu bằng cách sử Docker command, nhưng để tạo 1 image với những tuỳ chọn riêng, tôi đã viết một Dockerfile để xây dựng các container . Tôi cũng sử dụng Docker Compose để liên kết các container với nhau.
Redis container
Hãy sử dụng official Redis image từ Docker Hub cho container Redis. Nó được đóng gói sẵn với Redis Server được cài đặt và chạy trên cổng mặc định 6379. Vì vậy, bạn không cần phải cấu hình thêm bất kì điều gì miễn là bạn ok với giá trị mặc định. Bạn có thể chạy một container bằng cách :
docker run -d --name redis -p 6379:6379 redis
Phía trên bài viết đã nói ta sẽ tạo Redis image từ image ubuntu, bạn tạo Dockerfile sẽ giống như sau:
# Set the base image to Ubuntu FROM ubuntu # File Author / Maintainer MAINTAINER Le Tuan Minh # Update the repository and install Redis Server RUN apt-get update && apt-get install -y redis-server # Expose Redis port 6379 EXPOSE 6379 # Run Redis Server ENTRYPOINT ["/usr/bin/redis-server"]
Build image sử dụng Dockerfile :
docker build -t redis .
Node container
Đầu tiên chúng ta tạo src/index.js file cho application:
var express = require('express'), http = require('http'), redis = require('redis'); var app = express(); console.log(process.env.REDIS_PORT_6379_TCP_ADDR + ':' + process.env.REDIS_PORT_6379_TCP_PORT); // APPROACH 1: Using environment variables created by Docker // var client = redis.createClient( // process.env.REDIS_PORT_6379_TCP_PORT, // process.env.REDIS_PORT_6379_TCP_ADDR // ); // APPROACH 2: Using host entries created by Docker in /etc/hosts (RECOMMENDED) var client = redis.createClient('6379', 'redis'); app.get('/', function(req, res, next) { client.incr('counter', function(err, counter) { if(err) return next(err); res.send('This page has viewed ' + counter + ' times!'); }); }); http.createServer(app).listen(process.env.PORT || 8080, function() { console.log('Listening on port ' + (process.env.PORT || 8080)); });
Sau đó chúng ta cần tạo src/package.json file với các gói phụ thuộc cần để build và start node dịch vụ.
{ "name": "node", "version": "1.0.0", "description": "", "main": "index.js", "author": "Le Tuan Minh", "license": "ISC", "dependencies": { "express": "^4.12.3", "hiredis": "^0.5.0", "mocha": "^2.2.1", "redis": "^2.6.2" } }
Node Dockerfile:
Ubuntu base image pull từ Docker Hub.
Cài đặt Node.js sử dụng apt-get.
Chạy npm install ở thư mục nguồn.
Port 8080 được lắng nghe từ cái node container.
# Set the base image to Ubuntu FROM ubuntu # File Author / Maintainer MAINTAINER Le Tuan Minh # Install Node.js and other dependencies RUN apt-get update && apt-get -y install curl && curl -sL https://deb.nodesource.com/setup_5.x | bash && apt-get -y install python build-essential nodejs # ADD . /src ADD src/ /src WORKDIR /src RUN npm install # Expose port EXPOSE 8080 #Run app using nodemon CMD ["nodejs", "index.js"]
Build Docker image sử dụng Dockerfile:
docker build -t node .
NGiNX container
Ở đây tôi định nghĩa 1 file cấu hình nginx đơn giản cho 3 upstream servers :
worker_processes 4; events { worker_connections 1024; } http { upstream node-app { least_conn; server node1:8080 weight=10 max_fails=3 fail_timeout=30s; server node2:8080 weight=10 max_fails=3 fail_timeout=30s; server node3:8080 weight=10 max_fails=3 fail_timeout=30s; } server { listen 80; location / { proxy_pass http://node-app; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } }
Ở trên tôi tạo một máy chủ upstream node ứng dụng cân bằng tải giữa 3 máy chủ: node1, node2 và node3, trên cổng 8080. Tôi cũng đã định nghĩa cân bằng tải dựa trên số lượng các kết nối hoạt động trên mỗi máy chủ. Máy chủ Nginx lắng nghe trên cổng 8 và proxy pass request tới các upstream node ứng dụng dựa trên các policy cân bằng tải.
Chúng ta tạo image tùy chỉnh Nginx từ Ubuntu image, Dockerfile sẽ giống như sau:
# Set the base image to Ubuntu FROM ubuntu # File Author / Maintainer MAINTAINER Le Tuan Minh # Update the repository RUN apt-get update # Install necessary tools RUN apt-get install -y nano wget dialog net-tools # Download and Install Nginx RUN apt-get install -y nginx # Remove the default Nginx configuration file RUN rm -v /etc/nginx/nginx.conf # Copy a configuration file from the current directory ADD nginx.conf /etc/nginx/ # Append "daemon off;" to the configuration file RUN echo "daemon off;" >> /etc/nginx/nginx.conf # Expose ports EXPOSE 80 # Set the default command to execute when creating a new container CMD service nginx start
Build Docker image:
docker build -t nginx .
Composing các dịch vụ với Docker Compose
Chúng ta tạo file docker-compose.yml như sau :
nginx: build: ./nginx links: - node1:node1 - node2:node2 - node3:node3 ports: - "80:80" node1: build: ./node links: - redis ports: - "8080" node2: build: ./node links: - redis ports: - "8080" node3: build: ./node links: - redis ports: - "8080" redis: image: redis ports: - "6379"
Start các container :
docker-compose up -d
Tiến hành kiểm tra các process của các container :
- Kiểm tra trên server chạy các container
- Sử dụng trình duyệt để kiểm tra kết nối tới cổng 80
Docker vẫn còn là 1 công nghệ mới và đang trong quá trình phát triển, hiểu biết của người viết bài về docker cũng còn nhiều giới hạn. Rất mong các bạn sẽ có những góp ý cũng như trao đổi để chúng ta có thể hiểu rõ và làm chủ hoàn toàn được công nghệ này.