项目开发中,往往都需要启动多个容器,容器之间又相互依赖,存在着启动的顺序。docker-compose就是可以通过命令控制依次启动容器。
容器编排工具可以帮助我们批量地创建、调度和管理容器,帮助我们解决规模化容器的部署问题。
Docker 三种常用的编排工具:Docker Compose、Docker Swarm 和 Kubernetes。
本文主要是使用 docker-compose 实现react【nginx】、express【node】、mysql【mysql】搭建项目前端通过express访问mysql数据库的功能。
项目目录结构
.
├── docker-compose.yml
├── express-mysql
│ ├── app.js
│ ├── bin
│ ├── Dockerfile
│ ├── node_modules
│ ├── package.json
│ ├── public
│ ├── routes
│ ├── src
│ ├── views
│ └── yarn.lock
├── init.sql
├── react-express
│ ├── Dockerfile
│ ├── Dockerfile.build
│ ├── node_modules
│ ├── package.json
│ ├── public
│ ├── react-express.conf
│ ├── src
│ └── yarn.lock
└── start.sh
创建前端项目
使用 [create-react-app](https://create-react-app.bootcss.com/)
搭建前端项目,并安装axios插件,进行数据的调用。
npx create-react-app react-express
cd react-express
yarn add axios
npm start
调整首页内容
下载好项目,修改src/App.js
的内容,实现可以请求后端接口返回的数据。
import "./App.css";
import { useState, useEffect } from "react";
import axios from "axios";
function App() {
const [user, setUser] = useState([]);
useEffect(() => {
axios.get("http://localhost:8088/sql").then((res) => {
setUser(res.data);
});
}, []);
return (
<div className="App">
<header className="App-header">
{user.map((u, i) => (
<p key={i}> {u.username}</p>
))}
</header>
</div>
);
}
export default App;
添加Dockerfile文件
使用Dockerfile构建前端镜像。
FROM nginx
COPY ./build /usr/share/nginx/html
COPY ./react-express.conf /etc/nginx/conf.d
WORKDIR /usr/share/nginx/html
EXPOSE 80
# 启动ngnix
CMD ["nginx", "-g", "daemon off;"]
添加.dockerignore
文件,排除不需要打包到docker镜像的文件
node_modules
# testing
/coverage
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
添加nginx配置文件
添加react-express.conf
文件
server {
listen 80;
server_name localhost; # 如 www.baidu.com
root /usr/share/nginx/html; # 指向打包后的目录
location / {
index index.html;
}
}
生成前端镜像
只需要将编译后的build
文件添加到docker镜像中,生成镜像前,先执行下 npm run build
。
npm run build
docker build -t react-express .
可以看到成功生成react-express
镜像。并暴露端口为80,该镜像为后面执行docker-compose做准备。
创建后端项目
首先确保本地安装express;
npm install -g express
使用[express-generator](https://www.expressjs.com.cn/starter/generator.html)
生成器生产express-mysql
项目
mkdir express-mysql
cd express-mysql
npx express-generator
下载完成后,目录结构如下:
.
├── Dockerfile
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
├── routes
│ ├── index.js
│ └── users.js
├── views
│ ├── error.jade
│ ├── index.jade
│ └── layout.jade
└── yarn.lock
为了连接mysql数据库,新增src目录结构
.
├── Dockerfile
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
├── routes
│ ├── index.js
│ └── users.js
+ ├── src
+ │ ├── config.js
+ │ ├── db.js
├── views
│ ├── error.jade
│ ├── index.jade
│ └── layout.jade
└── yarn.lock
修改app.js设置跨域
// 在路由调用之前设置
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1')
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
// ...
连接mysql的配置
src/config.js
文件
module.exports = {
port: 3333, // express 服务启动端口
db: {
host: 'localhost', // 主机名
port: 8808, // MySQL 默认端口为 3306
user: 'root', // 使用 root 用户登入 MySQL
password: '123456', // MySQL 密码,用你自己的
database: 'blog', // 使用数据库
useConnectionPooling: true, // 使用连接池进行连接,否则过一会node连接的mysql就会断开,出现错误
connectionLimit: 50,
queueLimit: 0,
waitForConnection: true
}
}
src/db.js文件内容
const mysql = require("mysql");
// 获取数据库配置信息
const config = require("./config").db;
//创建一个mysql连接对象
let connection;
function handleError(err) {
if (err) {
// 如果是连接断开,自动重新连接
if (err.code === "PROTOCOL_CONNECTION_LOST") {
connect();
} else {
console.error(err.stack || err);
}
}
}
// 连接数据库
function connect() {
console.log("连接数据库 connect");
//创建一个mysql连接对象
connection = mysql.createPool(config);
connection.getConnection(handleError);
connection.on("error", handleError);
}
connect();
module.exports = connection;
进行sql查询
在routes/index.js
下设置sql查询
var express = require("express");
var router = express.Router();
const connection = require("../src/db");
router.get("/sql", function (req, res, next) {
// 第一个参数为 sql 语句,可以透过 js 自由组合
// 第二个参数为回调函数,err 表示查询异常、第二个参数则为查询结果(这里的查询结果为多个用户行)
connection.query("select username from user", (err, users) => {
if (err) {
res.send("query error"+ err);
} else {
// 将 MySQL 查询结果作为路由返回值
res.send(users);
}
});
});
module.exports = router;
构建后端镜像
新建Dockerfile
文件
FROM node:16.11.0
COPY ./ /app
WORKDIR /app
RUN npm config set registry https://registry.npm.taobao.org && npm install
EXPOSE 3000
CMD npm start
新建.dockerignore
文件
node_modules
*.lock
*.log
yarn-error.log
package-lock.json
在当前目录下,执行docker构建镜像的命令,测试下是否有问题。
docker build -t express-mysql .
初始化数据库
创建sql脚本,在容器启动后给mysql容器初始化数据。【初始化数据有很多其它方案,可以在创建镜像时通过修改配置将初始化数据存入镜像,有兴趣可自行搜索】,在这里只使用简单的手动处理方案,降低认知难度。
DROP TABLE IF EXISTS `user`;
create table user
(
id bigint auto_increment
primary key,
username varchar(255) not null
)
collate = utf8mb4_unicode_ci;
INSERT INTO blog.user (id, username) VALUES (1, 'admin');
INSERT INTO blog.user (id, username) VALUES (2, 'docker');
创建 mysql容器
docker run -d --name mysql-user -p 8087:3306 \
-v /data/docker-data/docker_mysql/conf:/etc/mysql/conf.d \
-v /data/docker-data/docker_mysql/logs:/logs \
-v /data/docker-data/docker_mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7
登录mysql并初始化数据
mysql -hlocalhost -P8087 -uroot -p123456 <<EOFuse blog;source /data/compose/init.sql;quitEOF
mysql -hlocalhost -P8087 -uroot -p123456 <<EOF
use blog;
source /data/compose/init.sql;
quit
EOF
docker-compose编排容器
到目前已经完成了前端、后端、数据库的创建,项目执行依赖多个容器启动,上面的过程非常繁琐,而且容易出现错误。接下来就使用docker-compose
可以使用一个命令将3个容器同时启动。
安装[docker-compose](https://docs.docker.com/compose/)
安装完成后查看版本信息
docker-compose version
---
docker-compose version 1.29.2, build unknown
docker-py version: 5.0.3
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.0.2k-fips 26 Jan 2017
新建yml文件
docker-compose.yml是docker-compose启动的默认文件
version: "3.1"
services:
react:
build:
context: "./react-express"
dockerfile: Dockerfile
depends_on:
- express
ports:
- "8086:80"
mysql:
image: mysql:5.7
container_name: mysql5
ports:
- "8087:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: "blog"
volumes:
- "/data/docker-data/docker_mysql/conf:/etc/mysql/conf.d"
- "/data/docker-data/docker_mysql/logs:/logs"
- "/data/docker-data/docker_mysql/data:/var/lib/mysql"
express:
build:
context: "./express-mysql"
dockerfile: Dockerfile
ports:
- "8088:3000"
depends_on:
- mysql
设置完成 yml 文件,执行启动命令
docker-compose up
# 或者 后台启动
docker-compose up -d
docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------------
compose_express_1 docker-entrypoint.sh /bin/ ... Up 0.0.0.0:8088->3000/tcp,:::8088->3000/tcp
compose_react_1 /docker-entrypoint.sh ngin ... Up 0.0.0.0:8086->80/tcp,:::8086->80/tcp
mysql5 docker-entrypoint.sh mysqld Up 0.0.0.0:8087->3306/tcp,:::8087->3306/tcp, 33060/tcp
一个命令就可以启动多个容器,并且组织好容器之间的依赖关系。
继续优化
创建前端镜像存在的问题.
每次打包前端镜像时,需要先完成 build 的阶段,也就是前端编译的过程。该过程其实也可以自动处理。
方案1:使用shell执行
在项目目录下创建 start.sh
文件, 将前端编译的过程放到外部node环境【jenkins、或者服务器】执行。
#!/bin/bash
cd react-express
yarn run build
cd ..
docker-compose up -d
mysql -hlocalhost -P8087 -uroot -p123456 <<EOF
use blog;
source ./init.sql;
quit
EOF
方案2:采用镜像多阶段构建
思路:将编译过程放到node环境中,打包出来build目录,然后将build目录拷贝到后边镜像内。
新建一个Dockerfile.build文件。
# 第一阶段,先对前端项目进行编译打包
FROM node:16.11.0 AS nodeapp
COPY ./ /app
WORKDIR /app
RUN yarn && yarn build
#多阶段构建,最终会以最后的镜像作为基础镜像
# 第二阶段,将打包的数据拷贝到后边镜像内,并创建nginx镜像
FROM nginx
COPY --from=nodeapp /app/build /usr/share/nginx/html
COPY ./react-express.conf /etc/nginx/conf.d
WORKDIR /usr/share/nginx/html
EXPOSE 80
# 启动ngnix
CMD ["nginx", "-g", "daemon off;"]
然后同步修改下docker-compose.yml
文件
version: "3.1"
services:
react:
build:
context: "./react-express"
dockerfile: Dockerfile.build
depends_on:
- express
ports:
- "8086:80"
mysql:
image: mysql:5.7
container_name: mysql5
ports:
- "8087:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: "blog"
volumes:
- "/data/docker-data/docker_mysql/conf:/etc/mysql/conf.d"
- "/data/docker-data/docker_mysql/logs:/logs"
- "/data/docker-data/docker_mysql/data:/var/lib/mysql"
express:
build:
context: "./express-mysql"
dockerfile: Dockerfile
ports:
- "8088:3000"
depends_on:
- mysql
到此这篇关于docker-compose实现容器任务编排的方法步骤的文章就介绍到这了,更多相关docker-compose 容器任务编排内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!