In this article we’re going to explore how to segment our app into a small network of multiple Docker containers, each with their own images.
在本文中,我们将探讨如何将我们的应用程序分割成一个由多个Docker容器组成的小型网络,每个容器都有自己的映像。
Single containers are easy enough to build imperatively in the command line, but doing anything more complicated can quickly get out of hand. Instead we’re going to use a new special type of config file called docker-compose.yml
. This declarative approach will allow us to quickly define our images in each container and setup the networking between them.
单个容器很容易在命令行中强制性地构建,但是做任何更复杂的事情都会很快失去控制。 相反,我们将使用一种新的特殊类型的配置文件docker-compose.yml
。 这种声明性方法将使我们能够在每个容器中快速定义图像并在它们之间建立网络。
In this example we’re going to be setting up an NGINX server, an Express server, and our React app. The goal being to have our client and server hosted separately with NGINX managing any requests to the correct container, so any http request to /api
will be sent to the server container and everything else to the client.
在此示例中,我们将设置NGINX服务器,Express服务器和React应用程序。 目标是让我们的客户端和服务器与NGINX分开托管,以管理对正确容器的任何请求,因此,对/api
任何http请求都将发送到服务器容器,其他所有内容都发送到客户端。
先决条件 (Prerequisites)
It would be helpful to know how to build images with Dockerfile, which you can brush up on here, but that will mostly be taken care of in the starter.
知道如何使用Dockerfile构建映像会很有帮助,您可以在此处进行梳理,但这在开始时会得到解决。
入门设置 (Starter Setup)
To save you the monotony of getting the basic React app and server setup and working, I’ve made this starter. The app itself is just an input that sends some text to get logged by the server, nothing fancy. Since we’re segmenting everything into their own containers, the client and server will have their own package.json files with dependencies, so remember to run npm install
on each folder individually if you want to test locally.
为了节省您获得基本React应用程序和服务器设置以及正常工作的单调性,我制作了这个入门工具 。 该应用程序本身只是一个输入,它发送一些文本以供服务器记录,没有什么花哨的地方。 由于我们将所有内容分段到各自的容器中,因此客户端和服务器将具有自己的具有依赖性的package.json文件,因此,如果要在本地进行测试,请记住分别在每个文件夹上运行npm install
。
NGINX安装 (NGINX Setup)
The NGINX server is different than the other containers. NGINX will act as the router between the React app and the server, directing requests to the correct container.
NGINX服务器不同于其他容器。 NGINX将充当React应用程序和服务器之间的路由器,将请求定向到正确的容器。
In a special configuration file, default.conf
, we’ll use upstream
to tell NGINX on what server port each container is running. Note that we’re referencing the service names that we defined over in docker-compose.yml
.
在一个特殊的配置文件default.conf
,我们将使用upstream
告诉NGINX每个容器正在哪个服务器端口上运行。 请注意,我们引用的是我们在docker-compose.yml
定义的服务名称。
server
is our controller, in this case our NGINX server. Docker just needs to know where it can find the controller and where we want to reroute traffic to depending on the request with proxy_pass
.
server
是我们的控制器,在这种情况下是我们的NGINX服务器。 Docker只需要知道在哪里可以找到控制器,以及我们想根据proxy_pass
的请求将流量重新路由到哪里。
upstream client {
server client:3000;
}
upstream server {
server server:4000;
}
server {
listen 80;
location / {
proxy_pass http://client;
}
location /api {
proxy_pass http://server;
}
}
Now we just need docker to put this configuration somewhere more useful. The NGINX container will already have an empty default.conf
file, so copying ours to its location will override the old one.
现在我们只需要docker将此配置放在更有用的位置。 NGINX容器将已经有一个空的default.conf
文件,因此将我们的文件复制到其位置将覆盖旧的文件。
FROM nginx
COPY ./default.conf /etc/nginx/conf.d/default.conf
Docker撰写 (Docker Compose)
version: '3'
services:
server:
build:
dockerfile: Dockerfile
context: ./server
volumes:
- /app/node_modules
- ./server:/app
nginx:
restart: always
build:
dockerfile: Dockerfile
context: ./controller
ports:
- '5000:80'
client:
build:
dockerfile: Dockerfile
context: ./client
volumes:
- /app/node_modules
- ./client:/app
Let’s go over exactly what this is trying to do:
让我们仔细看看这是怎么做的:
service
declares each container with its particular configuration, which we can name however we like.service
用其特定的配置声明每个容器,我们可以根据自己的喜好命名。build
tells how we want our container built, in this case which file to use and where it is withdockerfile
andcontext
.build
告诉我们如何build
容器,在这种情况下,使用哪个文件以及dockerfile
和context
在哪里。restart
tells Docker what to do if a container fails during runtime, in this case we always want it to attempt to restart.restart
告诉Docker如果容器在运行期间发生故障该怎么办,在这种情况下,我们总是希望其尝试重新启动。ports
remaps whatever port we want to the default port, just like the-p
flag when working in the terminal.ports
我们想要的任何端口重新映射到默认端口,就像在终端中工作时的-p
标志一样。volumes
are the persistent data connected to each container. We’re duplicating parts of our container and its dependencies in a way that when we throw the container away and start a new one it’ll have that cache to avoid the time of reinstalling everything.volumes
是连接到每个容器的持久数据。 我们以一种方式来复制容器的一部分及其依赖项,以便在我们丢弃容器并启动一个新容器时,将拥有该缓存,从而避免了重新安装所有内容的时间。
Finally we can create our services and attach our containers together using the docker-compose up
command and the --build
flag to build out our Dockerfiles.
最后,我们可以使用docker-compose up
命令和--build
标志创建服务并将容器附加在一起,以构建Dockerfile。
$ docker-compose up --build
This may take a while since it’s copying everything over and running npm install
, but when it’s done you should see server_1
, nginx_1
, and client_1
running simultaneously.
这可能需要一段时间,因为它会复制所有内容并运行npm install
,但是完成后,您应该看到server_1
, nginx_1
和client_1
同时运行。
总结思想 (Closing Thoughts)
This may have been a very simple use case, but Docker Compose is definitely one of the major tools you’ll be using with almost all of your Docker projects.
这可能是一个非常简单的用例,但是Docker Compose无疑是几乎所有Docker项目都将使用的主要工具之一。
翻译自: https://www.digitalocean.com/community/tutorials/workflow-multiple-containers-docker-compose