by João Henrique

通过JoãoHenrique

(How to create a full stack React/Express/MongoDB app using Docker)

In this tutorial, I will guide you through the process of containerizing a React FrontEnd, a Node/Express API, and a MongoDB database using Docker containers in a very simple way.

在本教程中,我将以非常简单的方式指导您完成使用Docker容器对React FrontEnd, Node / Express API和MongoDB数据库进行容器化的过程。

I won’t go into much detail about how to work with any of the technologies. Instead, I will leave links, in case you want to learn more about any of them.

我不会详细介绍如何使用任何技术。 相反,如果您想了解更多有关链接的信息,我将保留链接。

The objective is to give you a practical guide of how to containerize this simple Full-Stack App, to be used as a starting point, for you to build your own apps.

目的是为您提供有关如何容器化此简单的Full-Stack App的实用指南,以作为您构建自己的应用程序的起点。

您为什么要关心Docker ? (Why should you care about Docker?)

Docker is simply one of the most important technologies at the moment. It lets you run apps inside containers that are mostly isolated from “everything”.

Docker只是目前最重要的技术之一。 它使您可以在大多数与“一切”隔离的容器中运行应用程序。

Each container is like an individual virtual machine stripped out of everything that is not needed to run your app. This makes containers very light, fast and secure.

每个容器就像一个单独的虚拟机,剥离了运行应用程序不需要的所有内容。 这使容器非常轻便,快速且安全。

Containers are also meant to be disposable. If one goes rogue, you can kill it and make another just like it with no effort thanks to the container images system.

容器也应该是一次性的。 如果一个人流氓,可以借助容器映像系统毫不费力地杀死它并制造另一个

Another thing that makes Docker great is that the app inside containers will run the same in every system (Windows, Mac, or Linux). This is awesome if you are developing in your machine and then you want to deploy it to some cloud provider like GCP or AWS.

使Docker变得很棒的另一件事是,容器内的应用程序将在每个系统(Windows,Mac或Linux)中运行相同的应用程序。 如果您要在计算机中进行开发,然后要将其部署到某些云提供商(例如GCPAWS),那就太好了

(Getting ready!)
  1. Make sure you have Node and Docker running on your machine.
    确保您的计算机上运行了NodeDocker
  2. I will use the React/Express app we have built in the previous tutorial called Create a React FrontEnd, a Node/Express BackEnd and connect them together. You can follow that tutorial first or you can clone this GitHub repository with the boilerplate if you’re not interested in the process of creating React and Express apps.
    我将使用我们在上一个教程中构建的React / Express应用程序,该应用程序称为创建React FrontEnd,一个Node / Express BackEnd并将它们连接在一起 如果您对创建ReactExpress应用程序的过程不感兴趣,则可以先阅读该教程,也可以使用样板克隆GitHub存储库
  3. If you opt for using the repo, don't forget to npm install inside the Client and API folders to install all needed dependencies.
    如果您选择使用存储库,请不要忘记在ClientAPI文件夹内进行npm install来安装所有必需的依赖项。
  4. And… that’s about it. You’re all set to start containerizing stuff :)
(Dockerfile)

According to documentation:

根据文档:

a Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Docker can build images automatically by reading the instructions from a Dockerfile.

Dockerfile是一个文本文档,其中包含用户可以在命令行上调用以组装映像的所有命令。 Docker可以通过阅读Dockerfile中的指令来自动构建映像。

(Docker containers everywhere!)

Containerizing your app with Docker is as simple as creating a Dockerfile for each of your apps to first build an image, and then running each image to get your containers live.

使用Docker容器化应用程序非常简单, 只需为每个应用程序创建一个Dockerfile来首先构建映像,然后运行每个映像以使容器生效

(Containerize your Client)

To build our Client image you will be needing a Dockerfile. Let’s create one:

要构建我们的客户端映像,您将需要一个Dockerfile 。 让我们创建一个:

  1. Open the React/Express App in your favorite code editor (I’m using VS Code).
    在您最喜欢的代码编辑器中打开React / Express App (我正在使用VS Code )。
  2. Navigate to the Client folder.
    导航到“ 客户端”文件夹。
  3. Create a new file named Dockerfile.
    创建一个名为Dockerfile的新文件。
  4. Place this code inside it:
# Use a lighter version of Node as a parent imageFROM mhart/alpine-node:8.11.4
# Set the working directory to /clientWORKDIR /client
# copy package.json into the container at /clientCOPY package*.json /client/
# install dependenciesRUN npm install
# Copy the current directory contents into the container at /clientCOPY . /client/
# Make port 3000 available to the world outside this containerEXPOSE 3000
# Run the app when the container launchesCMD ["npm", "start"]

This will instruct docker to build an image (using these configurations) for our Client. You can read all about Dokerfile here.

这将指示docker为我们的客户端构建映像(使用这些配置)。 您可以在此处阅读有关Dokerfile的所有信息。

(Containerize your API)

To build our API image you will be needing another Dockerfile. Let’s create it:

要构建我们的API映像,您将需要另一个Dockerfile 。 创建它:

  1. Navigate to the API folder.
    导航到API文件夹。
  2. Create a new file named Dockerfile.
    创建一个名为Dockerfile的新文件。
  3. Place this code inside it:
# Use a lighter version of Node as a parent imageFROM mhart/alpine-node:8.11.4
# Set the working directory to /apiWORKDIR /api
# copy package.json into the container at /apiCOPY package*.json /api/
# install dependenciesRUN npm install
# Copy the current directory contents into the container at /apiCOPY . /api/
# Make port 80 available to the world outside this containerEXPOSE 80
# Run the app when the container launchesCMD ["npm", "start"]

This will instruct docker to build an image (using these configurations) for our API. You can read all about Dokerfile here.

这将指示docker为我们的API构建映像(使用这些配置)。 您可以在此处阅读有关Dokerfile的所有信息。

(Docker-Compose)

You could run each individual container using the Dokerfiles. In our case we have 3 containers to manage, so we will use docker-compose instead. Compose is a tool for defining and running multi-container Docker applications.

您可以使用Dokerfiles运行每个单独的容器。 在我们的例子中,我们要管理3个容器,因此我们将改用docker-compose。 Compose是用于定义和运行多容器Docker应用程序的工具。

Let me show you how simple it is to use it:

让我告诉您使用它有多么简单:

  1. Open the React/Express App in your code editor.
    在代码编辑器中打开React / Express App
  2. On your App main folder, create a new file and name it docker-compose.yml.
    在您的App主文件夹中,创建一个新文件,并将其命名为docker-compose.yml
  3. Write this code in the docker-compose.yml file:
    将此代码写入docker-compose.yml文件:
version: "2"
services:    client:        image: webapp-client        restart: always        ports:            - "3000:3000"        volumes:            - ./client:/client            - /client/node_modules        links:            - api        networks:            webappnetwork
api:        image: webapp-api        restart: always        ports:            - "9000:9000"        volumes:            - ./api:/api            - /api/node_modules        depends_on:            - mongodb        networks:            webappnetwork

What sorcery is that?

那是什么法术?

You should read all about docker-compose here.

您应该在此处阅读有关docker-compose的所有内容。

Basically, I’m telling Docker that I want to build a container called client, using the image webapp-client (which is the image we defined on our Client Dockerfile) that will be listening on port 3000. Then, I’m telling it that I want to build a container called api using the image webapp-api (which is the image we defined on our API Dockerfile) that will be listening on port 9000.

基本上,我是告诉Docker我要使用图像webapp-client (这是我们在客户端Dockerfile上定义的图像)构建一个名为client的容器。 它将在端口3000上监听。然后,我告诉我要使用将在端口9000上监听的映像webapp-api (这是我们在API Dockerfile上定义的映像)构建一个名为api的容器。

Keep in mind that there are many ways of writing a docker-compose.yml file. You should explore the documentation and use what better suits your needs.

请记住,有许多方法可以编写docker-compose.yml文件。 您应该浏览文档,并使用更适合您需要的文档。

添加一个MongoDB数据库 (Add a MongoDB database)

To add a MongoDB database is as simple as adding these lines of code to your docker-compose.yml file:

添加MongoDB数据库就像将以下代码行添加到docker-compose.yml文件一样简单:

mongodb:        image: mongo        restart: always        container_name: mongodb        volumes:            - ./data-node:/data/db        ports:            - 27017:27017        command: mongod --noauth --smallfiles        networks:            - webappnetwork

This will create a container using the official MongoDB image.

这将使用官方的MongoDB映像创建一个容器。

(Create a shared network for your containers)

To create a shared network for your container just add the following code to your docker-compose.yml file:

要为您的容器创建共享网络,只需将以下代码添加到docker-compose.yml文件中:

networks:    webappnetwork:        driver: bridge

Notice that you already defined each container of your app to use this network.

请注意,您已经定义了应用程序的每个容器以使用此网络。

In the end, your docker-compose.yml file should be something like this:

最后,您的docker-compose.yml文件应如下所示:

In the docker-compose.yml file, the indentation matters. Be aware of that.

docker-compose.yml文件中,缩进很重要。 注意这一点。

(Get your containers running)
  1. Now that you have a docker-compose.yml file, let’s build your images. Go to the terminal and on your App’s main directory run:
    现在您有了一个docker-compose.yml 文件,让我们构建您的图像。 转到终端,然后在您应用的主目录上运行:
docker-compose build

2. Now, to make Docker spin up the containers, just run:

2.现在,要使Docker启动容器,只需运行:

docker-compose up

And… just like magic, you now have your Client, your API, and your Database, all running in separated containers with only one command. How cool is that?

而且……就像魔术一样,您现在拥有了客户端,API和数据库,它们都仅需一个命令就可以在单独的容器中运行。 多么酷啊?

(Connect your API to MongoDB)
  1. First, let’s install Mongoose to help us with the connection to MongoDB. On your terminal type:
    首先,让我们安装Mongoose来帮助我们连接到MongoDB 。 在您的终端上输入:
npm install mongoose
  1. Now create a file called testDB.js on your API routes folder and insert this code:
    现在,在您的API路由文件夹中创建一个名为testDB.js的文件,并插入以下代码:
const express = require("express");const router = express.Router();const mongoose = require("mongoose");
// Variable to be sent to Frontend with Database statuslet databaseConnection = "Waiting for Database response...";
router.get("/", function(req, res, next) {    res.send(databaseConnection);});
// Connecting to MongoDBmongoose.connect("mongodb://mongodb:27017/test");
// If there is a connection error send an error messagemongoose.connection.on("error", error => {    console.log("Database connection error:", error);    databaseConnection = "Error connecting to Database";});
// If connected to MongoDB send a success messagemongoose.connection.once("open", () => {    console.log("Connected to Database!");    databaseConnection = "Connected to Database";});
module.exports = router;

Ok, let’s see what this code is doing. First, I import Express, ExpressRouter, and Mongoose to be used on our /testDB route. Then I create a variable that will be sent as a response telling what happened with the request. Then I connect to the database using Mongoose.connect(). Then I check if the connection is working or not, and change the variable (I’ve created earlier) accordingly. Finally, I use module.exports to export this route so that I’m able to use it on app.js file.

好的,让我们看看这段代码在做什么。 首先,我导入Express,ExpressRouter和Mongoose以在我们的/ testDB路由中使用。 然后,我创建一个变量,该变量将作为响应发送,告知请求发生了什么情况。 然后,我使用Mongoose.connect()连接到数据库。 然后,我检查连接是否正常工作,并相应地更改变量(我之前创建的变量)。 最后,我使用module.exports导出此路由,以便可以在app.js文件中使用它。

2. Now you have to “tell” Express to use that route you’ve just created. On your API folder, open the app.js file and insert this two lines of code:

2.现在,您必须“告诉” Express才能使用您刚刚创建的路由。 在您的API文件夹中,打开app.js文件,并插入以下两行代码:

var testDBRouter = require("./routes/testDB");app.use("/testDB", testDBRouter);

This will “tell” Express that every time there is a request to the endpoint /testDB, it should use the instructions on the file testDB.js.

这会“告诉” 快车 ,每一次有到端点的请求/ testdb的 ,它应该使用的文件testDB.js的说明。

3. Now let’s test if everything is working properly. Go to your terminal and press control + C to bring your containers down. Then run docker-compose up to bring them back up again. After everything is up and running, if you navigate to http://localhost:9000/testDB you should see the message Connected to Database.

3.现在,让我们测试是否一切正常。 转到终端,然后按Control + C放下容器。 然后运行docker-compose up使其再次备份。 一切启动并运行后,如果浏览至http:// localhost:9000 / testDB ,则应该看到消息Connected to Database。

In the end, your app.js file should look like this:

最后,您的app.js文件应如下所示:

Yep… it means the API is now connected to the database. But your FrontEnd doesn’t know yet. Let’s work on that now.

是的……这意味着该API现在已连接到数据库。 但是您的FrontEnd还不知道。 现在让我们开始吧。

React向数据库发出请求 (Make a request from React to the Database)

To check if the React app can reach the Database let’s make a simple request to the endpoint you defined on the previous step.

要检查React应用程序是否可以访问数据库,我们向您在上一步中定义的端点进行简单请求。

  1. Go to your Client folder and open the App.js file.
    转到“ 客户端”文件夹,然后打开App.js文件。
  2. Now insert this code below the callAPI() method:
    现在,将此代码插入callAPI()方法下面:
callDB() {    fetch("http://localhost:9000/testDB")        .then(res => res.text())        .then(res =>; this.setState({ dbResponse: res }))        .catch(err => err);}

This method will fetch the endpoint you defined earlier on the API and retrieve the response. Then it will store the response in the state of the component.

此方法将获取您先前在API上定义的端点并检索响应。 然后它将响应存储在组件的状态中

4. Add a variable to the state of the component to store the response:

4.在组件状态中添加一个变量以存储响应:

dbResponse: ""

3. Inside the lifecycle method componentDidMount(), insert this code to execute the method you’ve just created when the component mounts:

3.在生命周期方法componentDidMount()中,插入以下代码以执行组件装入时刚创建的方法:

this.callDB();

4. Finally, add another <;p> tag after the one you already have to display the response from the Database:

4.最后,在已经要显示来自数据库的响应的标记之后,添加另一个< ; p>标记:

<p className="App-intro">;{this.state.dbResponse}</p>

In the end, your App.js file should end up like this:

最后,您的App.js文件应如下所示:

(Finally, let’s see if everything is working)

On your browser, go to http://localhost:3000/ and if everything is working properly, you should see these three messages :

在浏览器上,转到http:// localhost:3000 / ,如果一切正常,您应该看到以下三则消息:

  1. Welcome to React
  2. API is working properly
  3. Connected to Database

Something like this:

像这样:

恭喜!!! (Congratulations!!!)

You now have a full stack app with a React FrontEnd, a Node/Express API and a MongoDB database. All running inside individual Docker containers that are orchestrated with a simple docker-compose file.

现在,您将拥有一个全栈应用程序,其中包含一个React FrontEnd,一个Node / Express API和一个MongoDB数据库。 所有运行在由简单docker-compose文件编排的单个Docker容器中。

This app can be used as a boilerplate to build your more robust app.

该应用程序可用作构建更强大应用程序的样板。

You can find all the code I wrote in the project repository.

您可以在项目存储库中找到我编写的所有代码。

Be Strong and Code On!!!

坚强并编码!!!

…and don’t forget to be awesome today ;)

…别忘了今天变得很棒;)

翻译自: https://www.freecodecamp.org/news/create-a-fullstack-react-express-mongodb-app-using-docker-c3e3e21c4074/