Nền tảng Docker cho phép các nhà phát triển đóng gói và chạy ứng dụng dưới dạng container. Một container là một tiến trình được cô lập chạy trên cùng một hệ điều hành chia sẻ, cung cấp một lựa chọn nhẹ hơn so với máy ảo. Dù container không phải là mới, chúng mang lại lợi ích — bao gồm cô lập tiến trình và chuẩn hóa môi trường — ngày càng quan trọng khi nhiều nhà phát triển sử dụng kiến trúc ứng dụng phân tán.
Khi xây dựng và mở rộng ứng dụng với Docker, điểm bắt đầu thường là tạo một image cho ứng dụng của bạn, bạn có thể chạy trong container. Image bao gồm mã ứng dụng, thư viện, file cấu hình, biến môi trường và runtime. Sử dụng image giúp chuẩn hóa môi trường trong container và chỉ chứa những gì cần thiết để xây dựng và chạy ứng dụng.
Trong bài hướng dẫn này, bạn sẽ tạo image ứng dụng cho một website tĩnh sử dụng framework Express và Bootstrap. Sau đó, bạn sẽ xây dựng container từ image đó và đẩy lên Docker Hub để sử dụng về sau. Cuối cùng, bạn sẽ kéo lại image từ kho Docker Hub và tạo container khác, thể hiện cách tái tạo và mở rộng ứng dụng.
Để tạo image, trước hết bạn cần tạo các file ứng dụng, bao gồm nội dung tĩnh, mã nguồn và phụ thuộc.
Tạo thư mục dự án trong thư mục home của người dùng không phải root. Ví dụ đặt tên node_project
:
mkdir node_project
cd node_project
Tạo file package.json
chứa thông tin phụ thuộc và các thông tin định danh khác:
nano package.json
Chèn nội dung sau, thay đổi tên tác giả và thông tin liên hệ:
{
"name": "nodejs-image-demo",
"version": "1.0.0",
"description": "nodejs image demo",
"author": "Sammy the Shark <[email protected]>",
"license": "MIT",
"main": "app.js",
"keywords": [
"nodejs",
"bootstrap",
"express"
],
"dependencies": {
"express": "^4.16.4"
}
}
File này bao gồm tên dự án, tác giả và giấy phép phân phối (MIT). Thuộc tính main
chỉ ra điểm vào ứng dụng là app.js
. Phần dependencies
liệt kê các thư viện cần thiết, ở đây là Express 4.16.4 trở lên.
Lưu và đóng file. Cài đặt các phụ thuộc trong dự án:
npm install
Chúng ta sẽ tạo một website cung cấp thông tin về cá mập. Ứng dụng có điểm vào chính là app.js
và thư mục views
chứa tài nguyên tĩnh. Trang chính index.html
cung cấp thông tin sơ bộ và liên kết đến trang chi tiết sharks.html
. Cả hai trang này sẽ nằm trong views
.
Mở app.js
để định nghĩa các route:
nano app.js
Thêm mã sau để tạo ứng dụng Express, đối tượng router, và định nghĩa thư mục cơ sở cùng cổng lắng nghe 8080:
const express = require('express');
const app = express();
const router = express.Router();
const path = __dirname + '/views/';
const port = 8080;
require
tải module express, tạo đối tượng app
và router
. router
chịu trách nhiệm điều hướng các yêu cầu HTTP.
Định nghĩa các tuyến bằng router
:
router.use(function (req, res, next) {
console.log('/' + req.method);
next();
});
router.get('/', function (req, res) {
res.sendFile(path + 'index.html');
});
router.get('/sharks', function (req, res) {
res.sendFile(path + 'sharks.html');
});
router.use
đăng ký middleware để ghi log các yêu cầu; router.get
định nghĩa phản hồi cho các đường dẫn /
và /sharks
.
Cuối cùng, kết nối middleware và tài nguyên tĩnh, lắng nghe trên cổng 8080:
app.use(express.static(path));
app.use('/', router);
app.listen(port, function () {
console.log('Example app listening on port 8080!');
});
Lưu và đóng file.
Tạo thư mục views
và file index.html
:
mkdir views
nano views/index.html
Thêm mã HTML sau để tạo trang chính:
<!DOCTYPE html>
<html lang="en">
<head>
<title>About Sharks</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="css/styles.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
</head>
<body>
<nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
<div class="container">
<button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
</button>
<a class="navbar-brand" href="#">Everything Sharks</a>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav mr-auto">
<li class="active nav-item"><a href="/" class="nav-link">Home</a></li>
<li class="nav-item"><a href="/sharks" class="nav-link">Sharks</a></li>
</ul>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1>Want to Learn About Sharks?</h1>
<p>Are you ready to learn about sharks?</p>
<br>
<p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a></p>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-6">
<h3>Not all sharks are alike</h3>
<p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.</p>
</div>
<div class="col-lg-6">
<h3>Sharks are ancient</h3>
<p>There is evidence to suggest that sharks lived up to 400 million years ago.</p>
</div>
</div>
</div>
</body>
</html>
Lưu và đóng file.
Tạo file sharks.html
trong views
có nội dung chi tiết về cá mập:
nano views/sharks.html
Thêm mã HTML sau:
<!DOCTYPE html>
<html lang="en">
<head>
<title>About Sharks</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="css/styles.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
</head>
<body>
<nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
<div class="container">
<button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
</button>
<a class="navbar-brand" href="/">Everything Sharks</a>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav mr-auto">
<li class="nav-item"><a href="/" class="nav-link">Home</a></li>
<li class="active nav-item"><a href="/sharks" class="nav-link">Sharks</a></li>
</ul>
</div>
</div>
</nav>
<div class="jumbotron text-center">
<h1>Shark Info</h1>
</div>
<div class="container">
<div class="row">
<div class="col-lg-6">
<p>
<div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
</div>
<img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
</p>
</div>
<div class="col-lg-6">
<p>
<div class="caption">Other sharks are known to be friendly and welcoming!</div>
<img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
</p>
</div>
</div>
</div>
</body>
</html>
Lưu và đóng file.
Tạo thư mục css
trong views
và tạo file styles.css
để tạo style tùy chỉnh:
mkdir views/css
nano views/css/styles.css
Thêm CSS:
.navbar {
margin-bottom: 0;
}
body {
background: #020A1B;
color: #ffffff;
font-family: 'Merriweather', sans-serif;
}
h1, h2 {
font-weight: bold;
}
p {
font-size: 16px;
color: #ffffff;
}
.jumbotron {
background: #0048CD;
color: white;
text-align: center;
}
.jumbotron p {
color: white;
font-size: 26px;
}
.btn-primary {
color: #fff;
text-color: #000000;
border-color: white;
margin-bottom: 5px;
}
img, video, audio {
margin-top: 20px;
max-width: 80%;
}
div.caption: {
float: left;
clear: both;
}
Lưu file.
Để bắt đầu ứng dụng, nếu bạn có tường lửa chỉ cho phép SSH, hãy mở cổng 8080:
sudo ufw allow 8080
Vào thư mục dự án và chạy:
cd ~/node_project
node app.js
Truy cập http://your_server_ip:8080
trên trình duyệt để xem trang chủ. Nhấn nút Get Shark Info để xem trang chi tiết về cá mập.
Nhấn CTRL+C
để tắt server.
Dockerfile định nghĩa môi trường container khi chạy ứng dụng. Tuân theo các hướng dẫn tối ưu, ta giảm số lớp ảnh và giới hạn chức năng image cho việc tái tạo ứng dụng tĩnh.
Tạo Dockerfile trong thư mục dự án:
nano Dockerfile
Chọn ảnh base là node:10-alpine
(phiên bản LTS Node.js đề xuất):
FROM node:10-alpine
Tạo thư mục node_modules
trong /home/node/app
và đặt quyền sở hữu cho user node
:
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
Đặt thư mục làm việc:
WORKDIR /home/node/app
Sao chép file package.json
và package-lock.json
:
COPY package*.json ./
Chuyển sang user node
:
USER node
Cài đặt các phụ thuộc:
RUN npm install
Sao chép toàn bộ mã ứng dụng, đổi quyền sở hữu cho user node
:
COPY . .
Mở cổng 8080:
EXPOSE 8080
Chạy ứng dụng:
CMD [ "node", "app.js" ]
Lưu và đóng Dockerfile.
Tạo file .dockerignore
để ngăn chặn sao chép các file/directory không cần thiết:
nano .dockerignore
Thêm nội dung:
node_modules
npm-debug.log
Dockerfile
.dockerignore
Lưu và đóng file.
Xây dựng image với tag bao gồm tên user Docker Hub:
sudo docker build -t your_dockerhub_username/nodejs-image-demo .
Kiểm tra các image:
sudo docker images
Chạy container:
sudo docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
Kiểm tra container chạy:
sudo docker ps
Mở trình duyệt đến http://your_server_ip
để xem trang chủ.
Đăng nhập Docker Hub:
sudo docker login -u your_dockerhub_username
Nhập mật khẩu khi được yêu cầu.
Đẩy image lên Docker Hub:
sudo docker push your_dockerhub_username/nodejs-image-demo
Kiểm tra container đang chạy:
sudo docker ps
Dùng container ID dừng container:
sudo docker stop container_id
Xem toàn bộ image:
docker images -a
Dọn dẹp container và image không dùng với:
docker system prune -a
Gõ y
để xác nhận.
Kéo lại image từ Docker Hub:
docker pull your_dockerhub_username/nodejs-image-demo
Kiểm tra image:
docker images
Tạo lại container như bước 3:
docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
Kiểm tra container:
docker ps
Truy cập http://your_server_ip
để xem ứng dụng đang chạy.
Trong bài hướng dẫn này, bạn đã tạo ứng dụng web tĩnh với Express và Bootstrap, xây dựng image Docker cho ứng dụng, tạo container từ image và đẩy lên Docker Hub. Bạn cũng đã học cách xóa và tái tạo container cũng như image từ repository Docker Hub.
Nếu bạn quan tâm học cách làm việc với Docker Compose hoặc Docker Machine để tạo setup đa container, hãy tham khảo các hướng dẫn liên quan. Ngoài ra, cũng có các hướng dẫn chia sẻ dữ liệu giữa các container và giữa container với host, rất hữu ích khi làm việc với Docker.
Bạn có thể duyệt thư viện hướng dẫn Docker đầy đủ trên trang của chúng tôi để tìm hiểu thêm về các chủ đề liên quan.