使用docker + docker-compose简化开发和部署

作者 : IT 大叔 本文共4706个字,预计阅读时间需要12分钟 发布时间: 2020-10-9

如今,开发由多种服务组成的项目非常普遍。最常见的示例是至少有一个后端和一个前端作为单独的应用程序。在更复杂的项目中,我们可以有更多的服务同时运行。

开发人员通常必须在其本地计算机上同时运行这些服务。

这样做的旧方法是简单地在单独的终端中手动启动每个服务。但是,正如您可能经历的那样,这很快就会变得很麻烦。

一些流行的工具(例如concurrentlynpm-run-all使之更容易)以增加依赖关系为代价。与yarn workspaces或结合使用lerna,它们可提供非常流畅的开发人员体验。

例如yarn dev,借助这些工具,开发人员可以键入唯一的命令,并自动启动其包含所有服务的整个堆栈。和单一CTRL+c的终端允许终止所有服务在一个单一的举动。真的很好吧?

但是,此方法有一些缺点:

  • 中更复杂的npm脚本 package.json
  • 新的依赖项已添加到项目中,需要维护
  • 各种各样的担忧,项目代码现在不仅用于构建服务,还用于协调服务
  • 如果您使用yarn-workspaces:现在每个服务也必须使用纱线。您将获得某种供应商锁定,将您的服务耦合在一起。如果我们希望每种服务使用不同的语言怎么办?

使用docker和docker-compose的更好方法

yarn-workspacesnpm-run-all我的所有项目一起使用了一段时间之后,最近我切换到仅使用dockerwith docker-compose

正如我发现的,docker-compose可以实现上述所有目标,并且还有更多方法:

✔️同时运行所有服务
✔️没有额外的npm依赖项,其增加的复杂性:否concurrently,否npm-run-all,否yarn workspaces等等
✔️100%分离和独立的服务,仅是标准应用程序
✔️能够为每种服务,不同的节点版本或程序包使用不同的语言经理
✔️更简单的心理模型

最重要的是,不仅为每个服务使用docker-compose一个单独Dockerfile的服务,而且docker-compose为开发中的业务流程使用一个单独的服务,我们获得了巨大的优势:

  • 能够在所有环境中使用完全相同的堆栈:开发,登台,生产,以及整个CD / CI管道。
  • 在任何计算机上极其轻松地复制开发环境。新开发人员只需要dockerdocker-compose开始工作。重新构建开发环境不会浪费更多的时间!
  • 不管您的服务需要不同的节点版本,还是ruby,python,clojure,数据库,cobol,...都可以,只需使用以下两个命令就可以在原始机器上启动所有内容:初始命令docker-compose build,然后是日常命令docker-compose up

假设我们在JavaScript中都有一个由前端和后端组成的堆栈。

这是我们的项目结构:

my-app
  - Readme.md

  - backend
    - Dockerfile
    - package.json
    - ...

  - frontend
    - Dockerfile
    - package.json
    - ...

  - dev
    - docker-compose.yml

笔记:

  • 每个服务可以使用不同的语言,节点版本,程序包管理器,...
  • docker-compose.yml完全可以放在项目的根文件夹中。我只是想创建一个新dev文件夹来对所有与开发相关的工具进行分组。它还有助于向所有开发人员(甚至我本人)澄清该docker-compose.yml文件仅供开发使用。

后端/ Dockerfile

我们backend/Dockerfile在编写时就考虑了生产环境,例如,说明RUN yarn --prod --frozen-lockfileCMD [ "yarn", "start" ]用于生产,但docker-compose稍后将使我们能够在本地覆盖某些部分以满足我们的开发需求。

# backend/Dockerfile =================
# (production-friendly)

FROM node:14-alpine

WORKDIR /usr/src/app

# Copy these files from your host into the image
COPY yarn.lock .
COPY package.json .

# Run the command inside the image filesystem
RUN yarn --prod --frozen-lockfile

# Copy the rest of your app's source code from your host to the image filesystem:
COPY . .

# Which port is the container listening on at runtime?
# This should be the same port your server is listening to:
EXPOSE 8080

# Start the server within the container:
CMD [ "yarn", "start" ]

前端/ Dockerfile

与我们的后端几乎完全相同Dockerfile,也出于生产目的而编写。
docker-compose将使我们能够在本地覆盖一些指令,仅用于开发。

# frontend/Dockerfile =================
# (production-friendly)

FROM node:14-alpine

WORKDIR /usr/src/app

COPY yarn.lock .
COPY package.json .

RUN yarn --prod --frozen-lockfile

COPY . .

EXPOSE 3000

CMD [ "yarn", "start" ]

dev / docker-compose.yml

version: "3"

services:
  backend:
    build: "../backend"
    ports:
      - 8080:8080
    command: sh -c "yarn && yarn dev"
    volumes:
      - ../backend:/usr/src/app

  frontend:
    build: "../frontend"
    ports:
      - 3000:3000
    command: sh -c "yarn && yarn dev"
    volumes:
      - ../frontend:/usr/src/app

在这里,在重用之前定义的2时Dockerfile,我们可以覆盖某些命令和参数。

在这种情况下,portscommand覆盖值EXPOSECMD

volumes让我们对我们的机器上的前端和后端文件夹映射到容器内的人。这意味着您现在可以在IDE中正常编辑项目文件,所有更改都会立即反映在容器中。

启动整个项目

对于第一次运行,在终端中,键入:

$ cd dev
$ docker-compose build

这将下载Dockerfiles(node:14-alpine)中定义的图像,并为前端和后端准备整个环境。

请注意,您最初只需要运行一次此命令,或者在修改之后只需运行一次Dockerfile

要运行整个堆栈并开始编码:

$ cd dev
$ docker-compose up

现在,您应该可以在http:// localhost:3000上访问前端,并在http:// localhost:8080上访问后端。

日常使用

从现在开始,所有npm脚本和命令都应该在容器内而不是在主机上执行。

例如,如果我们要将包添加classnames到前端:

# in a new terminal:
$ cd dev
$ docker-compose exec frontend yarn add classnames

老实说,这很麻烦,而且打字很多,您不觉得吗?
不用担心,我们将在下一节中介绍如何使其变得更好:

现在我们可以拥有美好的事物!

1)由于使用bash别名,击键次数更少

谁喜欢长时间的打字?没有人。

这是一个简单的解决方案:让我们aliases.sh在下添加一个文件dev

my-app
  - dev
    - aliases.sh

具有以下内容:

# my-app/dev/aliases.sh

alias be="docker-compose exec backend"
alias fe="docker-compose exec frontend"

让我们在当前终端中获取它:

$ . dev/aliases.sh

从现在开始:

# we can type this:
  $ fe yarn add classnames
  $ be yarn add -D nodemon

# instead of:
#   $ docker-compose exec frontend yarn add classnames
#   $ docker-compose exec backend yarn add -D nodemon

为了避免在每个终端中手动采购,我们也可以在以下方面一劳永逸地做到.bashrc

# in /home/<USER>/.bashrc
# at the very end, just add this line:

. /<PATH_TO_MY_APP>/dev/aliases.sh

我建议仅在持续处理项目时执行此操作,并在不再需要此新行时将其删除。

2)更可靠的部署到阶段,生产,...

多亏了Dockerfiles(为生产而编写,还记得吗?),我们可以在所有环境下的完全相同的OS和上下文中运行我们的服务:开发,测试,登台,生产...

例如,如果您使用Google Cloud Run,则现在可以Dockerfile为每个服务提供它,并且可以确保,如果您的代码在本地运行良好,则一旦部署,它也应该可以完美运行。

3)docker-compose附带的好处

例如,现在很容易根据项目需要添加其他容器。

假设我们需要postgres11.1版的数据库进行开发。我们可以将其添加到docker-compose.yml

version: "3"

services:
  backend:
    build: "../backend"
    ports:
      - 8080:8080
    command: sh -c "yarn && yarn dev"
    volumes:
      - ../backend:/usr/src/app

  frontend:
    build: "../frontend"
    ports:
      - 3000:3000
    command: sh -c "yarn && yarn dev"
    volumes:
      - ../frontend:/usr/src/app

  db:
    image: postgres:11.1
    command: "-c logging_collector=on"
    restart: always
    ports:
      - 5432:5432
    environment:
      POSTGRES_PASSWORD: changeme
      POSTGRES_USER: changeme
      POSTGRES_DB: changeme

  # Let's also provide an admin UI for the postgres 
  # database, often useful during development:

  adminer:
    image: adminer
    restart: always
    ports:
      - 5000:8080

结论

我们已经看到了如何在任何计算机上开发任何具有任何语言,任何数据库的并发运行服务,而无需在主机本身上安装这些服务。

我们只需要安装dockerdocker-compose(和一个IDE),就是这样!

通过这种方法,每个服务都只是一个完美包含的常规应用程序。

此外,我们现在可以在所有环境和所有开发人员的机器上的完全相同的系统(OS)中运行每个服务。

传统上,入职新开发人员和设置他们的开发环境可能需要几天的时间。使用这种方法,只需几分钟。

这也使得在使用不同语言或语言版本编写的不同项目之间切换几乎是瞬间的。

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 使用docker + docker-compose简化开发和部署

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论