距离上一次在掘金写文章,已通过去了半年多了(主要仍是本身水平差,不知道写什么好了)。node
不过新的一年,总要写点东西总结总结一下。mysql
最近也一直在使用docker
。因此就想者分享一下这方面的知识。不知道是否是最佳实践,欢迎各位踩我nginx
Docker
docker
的是什么,在掘金平台已经有不少篇文章有介绍了,我介绍的估计也没他们好。因此就当你们有必定的Docker基础了redis
因此这篇文章主要是实战方面的内容,具体理论的话,能够去搜搜其它文章了解学习一下。或者去官网sql
window
系统或者 macos
系统能够直接去官网下载 Docker Desktop
,连接:hub.docker.com/?overlay=on…docker
而后就是傻瓜式安装了,这边就不介绍了express
注意: window
下须要企业版才能安装,家庭版不能安装(或者安装比较麻烦)macos
docker-compose
在安装完 Docker Desktop
后,会默认自动安装好 docker-compose
npm
能够本身在命令行上试试,查看当前版本json
docker-compose -v
docker -v
复制代码
node
项目package.json
npm init -y
复制代码
express
,用koa
也行,看本身喜欢npm install express
复制代码
let express = require('express')
let os = require('os')
let app = express()
// 获取本机ip地址
function getLocalIpAddress () {
let ip = ''
let netInfo = os.networkInterfaces()
let osType = os.type()
if (osType === 'Windows_NT') {
for (const dev in netInfo) {
// win7的网络信息中显示为本地链接,win10显示为以太网
if (dev === '本地链接' || dev === '以太网') {
for (let j = 0; j < netInfo[dev].length; j++) {
if (netInfo[dev][j].family === 'IPv4') {
ip = netInfo[dev][j].address;
break;
}
}
}
}
} else if (osType === 'Linux') {
ip = netInfo.eth0[0].address;
}
return ip
}
app.get('/getJson', (request, response) => {
response.send({
title: 'Hello Express、Hello Docker',
ip: getLocalIpAddress(),
env: process.env.NODE_ENV
})
})
// 监听3000端口
app.listen(3000, () => {
console.log('server is started')
})
复制代码
Dockerfile
文件Docker
中镜像和容器的关系就像类与实例的关系Dockerfile
文件来生成,容器经过镜像来建立Dockerfile
用于生成镜像
# 指定的一个基础镜像
FROM node:latest
# 工做目录
WORKDIR /www/node-server/ # copy package.json 到工做目录中
COPY package.json /www/node-server/package.json # 安装依赖
RUN npm install # 拷贝当前目录的文件到工做目录中
# 若是有不须要忽略的文件,能够写在 .dockerignore 文件中,好比忽略 node_modules 文件夹
COPY . /www/node-server/ # 向外暴露3000端口
EXPOSE 3000
# 容器运行后执行的命令
CMD npm run start 复制代码
docker build .
复制代码
docker run --name node-server-1 -p 3000:3000 node-server
复制代码
docker-compose
构建前面咱们要使用容器时,须要先定义 Dockerfile
文件,而后使用 docker build
、docker run
等命令操做容器。
然而咱们的系统通常都包含上百的服务,每一个服务又有多个实例,若是全手动来启动关闭的话,那工做量之大可想而知
那经过 docker-compose
能够轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具
docker-compose.yml
文件docker-compose.yml
文件version: "3"
services: # 服务列表
node: # node 服务
build: . # Dockerfile 的目录,用于构建镜像
container_name: node-server-1 # 容器名称
ports: # 暴露的端口
- "3000:3000"
restart: always # 自动重启
environment: # 设置环境变量
- NODE_ENV=production
command: npm run start # 覆盖容器启动后默认执行的命令
复制代码
docker-compose build
复制代码
docker-compose up -d
复制代码
不出意外的话,经过浏览器访问3000
端口也是能正常访问
好比咱们如今须要构建一个 nginx
服务来将请求代理到咱们的 node-server
,那咱们须要构建两个服务
那么问题来了
nginx
容器如何使用个人本身的nginx.conf
配置文件
volumes
文件映射nginx
容器和 node-server
容器如何进行通讯
docker-inspect
命令来查看 node-server
容器的IP
地址,而后修改nginx.conf
的配置、networks
和links
docker
容器每次从新构建运行时,IP 地址不必定是同样的,因此每次都要修改nginx.conf
的配置,因此方案1的效率显然是低下的。
新增一个 nginx.conf
配置文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
upstream node-server {
server node:3000;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://node-server/;
}
}
}
复制代码
docker-compose.yml
文件# docker-compose.yml
version: "3"
services: # 服务
node: # node 服务
build: . # Dockerfile 的目录,用于构建镜像
container_name: node-server-1 # 容器名称
ports: # 暴露的端口
- "3000:3000"
restart: always # 自动重启
environment:
- NODE_ENV=production
networks: # 加入网络
- "my-network"
command: npm run start # 覆盖容器启动后默认执行的命令
nginx:
image: nginx:latest 指定 nginx 镜像
ports: # 将本机的 8080 端口映射到容器的80端口
- "8080:80"
container_name: nginx-node
restart: always
volumes: # 映射本机 F:/nginx.conf 文件到 容器的 /etc/nginx/nginx.conf:ro 文件
- "F:/nginx.conf:/etc/nginx/nginx.conf:ro"
networks:
- "my-network"
links: # 设置 node 服务别名,实际上是设置/etc/hosts的域名解析
- "node"
depends_on: # 指定依赖于哪一个服务
- node
networks: # 网络
my-network: # 网络名称
driver: bridge
复制代码
# 删除上次构建的容器
docker-compose down
# 从新构建镜像 --force-rm 删除构建过程当中的临时容器。
docker-compose build --force-rm
# 运行容器
docker-compose up -d
复制代码
不出意外的话,经过浏览器访问本地的8080端口,是能够访问到 node-server
的
按着上面的套路,能够继续扩展 redis
、mysql
服务等,也是经过加入 network
和 links
来进行相互通讯
这部分就不进行介绍了
当用户量比较小的状况下,咱们一个 node 服务就够用了,当用户量大的时候,就一个 node 服务的话,就显得力不从心了。
通常状况下都是升级机器,加服务,经过 nginx
进行负载均衡
那咱们如何经过 docker-compose 快速的水平扩展服务呢?
scale
docker-compose 给咱们提供了一个 scale 命令,用于在本机下快速构建多个服务
# 删除上次构建的容器
docker-compose down
# 从新构建镜像 --force-rm 删除构建过程当中的临时容器。
docker-compose build --force-rm
# 运行容器 增长 --scale node=5
docker-compose up -d --scale node=5
复制代码
经过--scale node=5
咱们构建5个node服务
不过不出意外的话,是会构建失败的,报端口占用错误
由于咱们的每一个node服务都占用了 3000 本机的端口。
因此咱们须要修改一下 docker-compose.yml
文件,只暴露容器的3000端口,不暴露本机的端口
# docker-compose.yml
version: "3"
services: # 服务
node: # node 服务
build: . # Dockerfile 的目录,用于构建镜像
# container_name: node-server-1 # 容器名称
# ports: # 暴露的端口
# - "3000:3000"
expose:
- "3000"
restart: always # 自动重启
environment:
- NODE_ENV=production
networks: # 加入网络
- "my-network"
command: npm run start # 覆盖容器启动后默认执行的命令
nginx:
image: nginx:latest 指定 nginx 镜像
ports: # 将本机的 8080 端口映射到容器的80端口
- "8080:80"
container_name: nginx-node
restart: always
volumes: # 映射本机 F:/nginx.conf 文件到 容器的 /etc/nginx/nginx.conf:ro 文件
- "F:/nginx.conf:/etc/nginx/nginx.conf:ro"
networks:
- "my-network"
links: # 设置 node 服务别名,实际上是设置/etc/hosts的域名解析
- "node"
depends_on: # 指定依赖于哪一个服务
- node
networks: # 网络
my-network: # 网络名称
driver: bridge
复制代码
# 运行容器 增长 --scale node=5
docker-compose up -d --scale node=5
复制代码
不出意外的话,此次能够构建成功
经过 docker ps -a
能够查看当前运行的容器
docker ps -a
复制代码
不出意外的话,经过nginx
访问,负载均衡没有生效,每次访问获得的ip
地址一直是同一个
咱们经过 docker inspect nginx-node
命令,在查看一下 nginx
容器的信息
docker inspect nginx-node
复制代码
能够看到 "node-server_node_3:node"
,咱们nginx
配置了server node:3000;
,因此每次请求,nginx
都将请求代理到node-server_node_3
这个node服务上了,
upstream node-server {
server node:3000;
}
复制代码
因此咱们修改一下 nginx.conf
配置,这样就能将请求代理到不一样的机器上了
upstream node-server {
upstream node-server {
server node_1:3000 weight=3; # 加权重
server node_2:3000;
server node_3:3000;
server node_4:3000;
server node_5:3000;
}
}
复制代码
咱们目前的扩展是单机环境下的scale,不管将service扩展到多少,只能限制在单机环境下。可是一台服务器的资源是有限的,那么如何扩展多台服务器?那么就是须要使用swarm技术了。这个接下来有机会在分享吧
因为技术水平有限,有写的很差的地方欢迎指出,轻喷!
欢迎关注公众号“码上开发”,天天分享最新技术资讯