網站首頁 編程語言 正文
項目開發中,往往都需要啟動多個容器,容器之間又相互依賴,存在著啟動的順序。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"); /* GET home page. */ router.get("/sql", function (req, res, next) { /* 使用 connection.query 來執行 sql 語句 */ // 第一個參數為 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
原文鏈接:https://blog.csdn.net/shenshuai89/article/details/127842097
相關推薦
- 2022-03-22 詳解_beginthreadex()創建線程_C 語言
- 2023-01-27 C#實現拆分合并Word表格中的單元格_C#教程
- 2022-10-25 python庫-dotenv包?及?.env配置文件詳解_python
- 2022-08-15 C語言排序算法實現
- 2022-07-31 C語言數據結構算法基礎之循環隊列示例_C 語言
- 2022-04-20 Android實現將View轉化為圖片并保存到本地_Android
- 2022-05-19 ASP.NET?Core框架探索之Authentication的權限認證過程解析_實用技巧
- 2022-06-08 如何在springboot中使用Thymeleaf
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支