Docker提供了轻巧的容器来与基础架构隔离运行服务,因此我们可以快速提供软件。在本教程中,我将向您展示如何使用Docker Compose和Nginx。
相关文章:
- React + Node.js + Express + MongoDB example: CRUD App
- React + Node.js Express + MongoDB: User Authentication with JWT example
- Integrate React with Node.js Express on same Server/Port
带有Docker概述的Mern Stack应用程序
假设我们有一个Fullstack React + Nodejs Express + MongoDB应用程序(Mern stack)。
问题是要容忍一个需要多个Docker容器的系统:
- 对UI的反应
- node.js for api
- 数据库的mongodb
Docker组成的构成可帮助我们更容易,更有效地设置系统,而不是仅使用Docker。我们将遵循以下步骤:
- 设置Nodejs应用程序与MongoDB数据库一起工作。
- 为nodejs应用创建dockerfile。
- 设置React App。
- 为React App创建Dockerfile。
- 写docker在yaml文件中构成配置。
- 设置Docker组成的环境变量
- 运行系统。
目录结构:
设置nodejs app
您可以从以下教程中的一个:
中读取并获取github源代码- Node.js, Express & MongoDb: Build a CRUD Rest Api example
- Node.js + MongoDB: User Authentication & Authorization with JWT
使用上面的代码库,我们将nodejs项目放入 bezkoder-api 文件夹中,然后修改某些文件以与环境变量一起使用。
首先,让我们将dotenv
模块添加到 package.json 。
{
...
"dependencies": {
"dotenv": "^10.0.0",
...
}
}
接下来,我们在 server.js 中导入dotenv
并使用process.env
来设置CORS和端口。
require("dotenv").config();
...
var corsOptions = {
origin: process.env.CLIENT_ORIGIN || "http://localhost:8081"
};
app.use(cors(corsOptions));
..
// set port, listen for requests
const PORT = process.env.NODE_DOCKER_PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
然后,我们更改修改数据库配置和初始化。
app / config / db.config.js
const {
DB_USER,
DB_PASSWORD,
DB_HOST,
DB_PORT,
DB_NAME,
} = process.env;
module.exports = {
url: `mongodb://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?authSource=admin`
};
我们还需要制作 .env 示例文件,以显示所有必要的参数。
bezkoder-api / .env.sample
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=bezkoder_db
DB_PORT=27017
NODE_DOCKER_PORT=8080
CLIENT_ORIGIN=http://127.0.0.1:8081
为nodejs应用创建Dockerfile
Dockerfile定义了Docker用于设置Node.js应用程序环境的命令列表。因此,我们将文件放入 bezkoder-api 文件夹中。
因为我们将使用Docker组成,所以我们不会在此Dockerfile中定义所有配置命令。
bezkoder-api / dockerfile
FROM node:14
WORKDIR /bezkoder-api
COPY package.json .
RUN npm install
COPY . .
CMD npm start
让我解释一些要点:
-
FROM
:安装node.js版本的图像。 -
WORKDIR
:工作目录的路径。 -
COPY
:复制 package.json 文件到容器,然后第二个复制项目目录中的所有文件。 -
RUN
:在容器中执行命令行:npm install
在 package.json 。 中安装依赖项
-
CMD
:构建图像后运行脚本npm start
。
设置React App
您可以从以下教程中的一个:
中读取并获取github源代码- React CRUD example to consume Web API
- React Typescript CRUD example to consume Web API
- React Redux CRUD App example with Rest API
- React Hooks CRUD example to consume Web API
- React Table example: CRUD App with react-table v7
- React Material UI examples with a CRUD Application
- React JWT Authentication & Authorization example
- React + Redux: JWT Authentication & Authorization example
使用上面的代码库,我们将React项目放入 bezkoder-ui 文件夹中,并进行一些工作。
首先,让我们删除 .env 文件,因为我们将与Docker的环境变量一起工作。
然后,我们打开 http-common.js ,用于用process.env.REACT_APP_API_BASE_URL
更新axios实例的baseURL
。
import axios from "axios";
export default axios.create({
baseURL: process.env.REACT_APP_API_BASE_URL || 'http://localhost:8080/api',
headers: {
"Content-type": "application/json"
}
});
创建React App
的Dockerfile我们将在Nginx服务器后面部署React应用程序。
与nodejs相同,我们将dockerfile放入 bezkoder-ui 文件夹中。
bezkoder-upi / dockerfile
# Stage 1
FROM node:14 as build-stage
WORKDIR /bezkoder-ui
COPY package.json .
RUN npm install
COPY . .
ARG REACT_APP_API_BASE_URL
ENV REACT_APP_API_BASE_URL=$REACT_APP_API_BASE_URL
RUN npm run build
# Stage 2
FROM nginx:1.17.0-alpine
COPY --from=build-stage /bezkoder-ui/build /usr/share/nginx/html
EXPOSE $REACT_DOCKER_PORT
CMD nginx -g 'daemon off;'
有两个阶段:
-
阶段1:构建React应用程序
-
FROM
:安装node.js版本的图像。 -
WORKDIR
:工作目录的路径。 -
COPY
:复制 package.json 文件到容器,然后第二个复制项目目录中的所有文件。 -
RUN
:在容器中执行命令行:npm install
在 package.json 。 中安装依赖项
-
ARG
和ENV
:获取参数和设置环境变量(需要前缀REACT_APP_
)。 - 运行脚本
npm run build
构建图像后,产品将存储在 build 文件夹中。
-
-
阶段2:将React应用程序与Nginx
一起服务- 安装 nginx的图像 Alpine版本。
- 将React构建从阶段1复制到
/usr/share/nginx/html
文件夹中。 - 公开端口(应为
80
)到docker主机。 -
daemon off;
指令告诉nginx留在前景中。
写Docker为Mern应用程序撰写
在项目目录的根部,我们将为Mern堆栈创建 docker-compose.yml 文件。遵循Docker定义的version 3语法:
version: '3.8'
services:
mongodb:
bezkoder-api:
bezkoder-ui:
volumes:
networks:
-
version
:将使用Docker组成的文件格式版本。 -
services
:孤立容器中的单个服务。我们的应用程序有三个服务:bezkoder-ui
(react),bezkoder-api
(nodejs)和mongodb
(mongodb数据库)。 -
volumes
:命名量,使我们的数据在重新启动后保持活力。 -
networks
:促进容器之间的通信
让我们实现详细信息。
docker-compose.yml
version: '3.8'
services:
mongodb:
image: mongo:5.0.2
restart: unless-stopped
env_file: ./.env
environment:
- MONGO_INITDB_ROOT_USERNAME=$MONGODB_USER
- MONGO_INITDB_ROOT_PASSWORD=$MONGODB_PASSWORD
ports:
- $MONGODB_LOCAL_PORT:$MONGODB_DOCKER_PORT
volumes:
- db:/data/db
networks:
- backend
bezkoder-api:
depends_on:
- mongodb
build: ./bezkoder-api
restart: unless-stopped
env_file: ./.env
ports:
- $NODE_LOCAL_PORT:$NODE_DOCKER_PORT
environment:
- DB_HOST=mongodb
- DB_USER=$MONGODB_USER
- DB_PASSWORD=$MONGODB_PASSWORD
- DB_NAME=$MONGODB_DATABASE
- DB_PORT=$MONGODB_DOCKER_PORT
- CLIENT_ORIGIN=$CLIENT_ORIGIN
networks:
- backend
- frontend
bezkoder-ui:
depends_on:
- bezkoder-api
build:
context: ./bezkoder-ui
args:
- REACT_APP_API_BASE_URL=$CLIENT_API_BASE_URL
ports:
- $REACT_LOCAL_PORT:$REACT_DOCKER_PORT
networks:
- frontend
volumes:
db:
networks:
backend:
frontend:
-
mongodb :
-
image
:官方Docker Image -
restart
:配置restart policy -
env_file
:指定我们 .env 路径,我们将在以后创建 -
environment
:使用环境变量提供设置 -
ports
:指定端口将被使用 -
volumes
:地图卷文件夹 -
networks
:加入backend
网络
-
-
bezkoder-api :
-
depends_on
:依赖顺序, MongoDB 在 bezkoder-api 之前启动了服务 -
build
:在 dockerfile 中定义的构建时间上应用的配置选项
-
-
environment
:节点应用程序使用的环境变量 -
networks
:加入backend
和frontent
Networks
bezkoder-ui :
-
depends_on
:在bezkoder-api
之后开始 -
build-args
:添加构建参数 - 仅在构建过程中访问的环境变量 才能访问
-
networks
:仅加入frontent
网络
您应该注意,主机端口(LOCAL_PORT
)和容器端口(DOCKER_PORT
)不同。网络服务到服务通信使用容器端口,外部使用主机端口。
docker构成环境变量
在服务配置中,我们使用了 .env 文件中定义的环境变量。现在我们开始编写它。
.env
MONGODB_USER=root
MONGODB_PASSWORD=123456
MONGODB_DATABASE=bezkoder_db
MONGODB_LOCAL_PORT=7017
MONGODB_DOCKER_PORT=27017
NODE_LOCAL_PORT=6868
NODE_DOCKER_PORT=8080
CLIENT_ORIGIN=http://127.0.0.1:8888
CLIENT_API_BASE_URL=http://127.0.0.1:6868/api
REACT_LOCAL_PORT=8888
REACT_DOCKER_PORT=80
与Docker Compose
运行Mern堆栈我们只能使用一个命令轻松地运行整个命令:
docker-compose up
docker会拉动mongodb和node.js images(如果我们的计算机之前没有它)。
服务可以通过命令在后台运行:
docker-compose up -d
$ docker-compose up -d
Creating network "react-node-mongodb_backend" with the default driver
Creating network "react-node-mongodb_frontend" with the default driver
Creating volume "react-node-mongodb_db" with default driver
Pulling mongodb (mongo:5.0.2)...
5.0.2: Pulling from library/mongo
16ec32c2132b: Pull complete
6335cf672677: Pull complete
cbc70ccc8ebe: Pull complete
0d1a3c6bd417: Pull complete
960f3b9b27d3: Pull complete
aff995a136b4: Pull complete
4249be7550a8: Pull complete
cc105ff5aa3c: Pull complete
82819807d07a: Pull complete
81447d2c233f: Pull complete
Digest: sha256:93ea50c5f15f9814870b3509449d327c5bc4d38f2b17c20acec528472811a723
Status: Downloaded newer image for mongo:5.0.2
Building bezkoder-api
Sending build context to Docker daemon 20.48kB
Step 1/6 : FROM node:14
---> 256d6360f157
Step 2/6 : WORKDIR /bezkoder-api
---> Running in 630b36161cfc
Removing intermediate container 630b36161cfc
---> cce099c5509c
Step 3/6 : COPY package.json .
---> 966883cd8e24
Step 4/6 : RUN npm install
---> Running in 246256e84187
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN node-express-mongodb@1.0.0 No repository field.
added 82 packages from 128 contributors and audited 82 packages in 8.017s
2 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Removing intermediate container 246256e84187
---> bdab72a5d37b
Step 5/6 : COPY . .
---> e9069d0ee44a
Step 6/6 : CMD npm start
---> Running in 6f63286cae18
Removing intermediate container 6f63286cae18
---> 65452914f005
Successfully built 65452914f005
Successfully tagged react-node-mongodb_bezkoder-api:latest
WARNING: Image for service bezkoder-api was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Building bezkoder-ui
Sending build context to Docker daemon 67.07kB
Step 1/12 : FROM node:14 as build-stage
---> 256d6360f157
Step 2/12 : WORKDIR /bezkoder-ui
---> Running in e135a434b996
Removing intermediate container e135a434b996
---> 80292facc18b
Step 3/12 : COPY package.json .
---> 595fbe352edd
Step 4/12 : RUN npm install
---> Running in 9d8ef80ff165
added 1661 packages from 793 contributors and audited 1666 packages in 115.944s
94 packages are looking for funding
run `npm fund` for details
found 10 vulnerabilities (1 low, 5 moderate, 4 high)
run `npm audit fix` to fix them, or `npm audit` for details
Removing intermediate container 9d8ef80ff165
---> 18a4f1382bc7
Step 5/12 : COPY . .
---> f99e2a8ef053
Step 6/12 : ARG REACT_APP_API_BASE_URL
---> Running in 47dca1457fb2
Removing intermediate container 47dca1457fb2
---> 8986f1482c8d
Step 7/12 : ENV REACT_APP_API_BASE_URL=$REACT_APP_API_BASE_URL
---> Running in 95687ba2d936
Removing intermediate container 95687ba2d936
---> 7a20778bca2b
Step 8/12 : RUN npm run build
---> Running in d0074ed04394
> react-crud@0.1.0 build /bezkoder-ui
> react-scripts build
Creating an optimized production build...
Compiled successfully.
File sizes after gzip:
52.78 KB build/static/js/2.c9e8967b.chunk.js
22.71 KB build/static/css/2.fa6c921b.chunk.css
2.39 KB build/static/js/main.aae2fe51.chunk.js
776 B build/static/js/runtime-main.99b514f4.js
144 B build/static/css/main.9c6cdb86.chunk.css
The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s build
Find out more about deployment here:
bit.ly/CRA-deploy
Removing intermediate container d0074ed04394
---> 9cd424a1901b
Step 9/12 : FROM nginx:1.17.0-alpine
---> bfba26ca350c
Step 10/12 : COPY --from=build-stage /bezkoder-ui/build /usr/share/nginx/html
---> 2b4cbdbd908e
Step 11/12 : EXPOSE $REACT_DOCKER_PORT
---> Running in ced23b1795d6
Removing intermediate container ced23b1795d6
---> 2850341d70f0
Step 12/12 : CMD nginx -g 'daemon off;'
---> Running in d596e17eec46
Removing intermediate container d596e17eec46
---> fef41917c48b
Successfully built fef41917c48b
Successfully tagged react-node-mongodb_bezkoder-ui:latest
WARNING: Image for service bezkoder-ui was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating react-node-mongodb_mongodb_1 ... done
Creating react-node-mongodb_bezkoder-api_1 ... done
Creating react-node-mongodb_bezkoder-ui_1 ... done
现在您可以检查当前的工作容器:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9ee5ce3c370 react-node-mongodb_bezkoder-ui "/bin/sh -c 'nginx -…" Up 2 minutes Up 2 minutes 0.0.0.0:8888->80/tcp, :::8888->80/tcp react-node-mongodb_bezkoder-ui_1
f0c7d4174bdb react-node-mongodb_bezkoder-api "docker-entrypoint.s…" Up 2 minutes Up 2 minutes 0.0.0.0:6868->8080/tcp, :::6868->8080/tcp react-node-mongodb_bezkoder-api_1
2f8390fc81dd mongo:5.0.2 "docker-entrypoint.s…" Up 2 minutes Up 2 minutes 0.0.0.0:7017->27017/tcp, :::7017->27017/tcp react-node-mongodb_mongodb_1
和docker图像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
react-node-mongodb_bezkoder-ui latest fef41917c48b 3 minutes ago 22MB
react-node-mongodb_bezkoder-api latest 65452914f005 6 minutes ago 961MB
mongo 5.0.2 269b735e72cb 7 minutes ago 682MB
测试React UI:
mongoDB数据库:
和node.js express api:
停止应用程序
停止所有运行容器也很简单,只需一个命令:
docker-compose down
$ docker-compose down
Stopping react-node-mongodb_bezkoder-ui_1 ... done
Stopping react-node-mongodb_bezkoder-api_1 ... done
Stopping react-node-mongodb_mongodb_1 ... done
Removing react-node-mongodb_bezkoder-ui_1 ... done
Removing react-node-mongodb_bezkoder-api_1 ... done
Removing react-node-mongodb_mongodb_1 ... done
Removing network react-node-mongodb_backend
Removing network react-node-mongodb_frontend
如果您需要停止并删除 docker-compose.yml 文件中任何服务使用的所有容器,网络和所有图像,请使用命令:
docker-compose down --rmi all
结论
今天,我们成功地使用了Docker和Nginx创建了MERN应用程序。现在我们可以以一种非常简单的方式部署mern堆栈:react + nodejs express和mongodb: docker-compose.yml 。。
您可以将这种方式应用于以下项目之一:
- React + Node.js + Express + MongoDB example: CRUD App
- React + Node.js Express + MongoDB: User Authentication with JWT example
快乐学习!再次见。
源代码
本教程的源代码可以在Github中找到。