如何忽略要在 docker 构建上下文中发送的文件夹

Ibt*_*tif 14 docker docker-build

由于我的项目结构,我面临着大型 docker 构建上下文的问题。在我的根目录中,我有用于公共代码和微服务文件夹的 lib 文件夹。现在我想为 miscroservice1 构建只包含 lib 文件夹并忽略其他微服务。

我在根文件夹中运行 docker build 命令,因为在 microservice 文件夹中运行命令给出错误 Forbidden path outside of build context

rootFolder
-- lib
-- microservice1/Dockerfile
-- microservice2/Dockerfile
-- microservice3/Dockerfile
Run Code Online (Sandbox Code Playgroud)

我有两个解决方案,但暂时没有尝试

  1. 在我的微服务文件夹中为 lib 添加符号链接
  2. 为每个 docker build 编写脚本以在特定的微服务文件夹中添加 lib 文件夹,然后运行 ​​docker build。

我正在尝试上述两种解决方案。任何人都可以建议任何最佳做法吗?

Min*_*ato 22

您可以.dockerignore在根目录中创建并添加

microservice1/
microservice2/
microservice3/
Run Code Online (Sandbox Code Playgroud)

对此,就像.gitignore在跟踪文件期间一样,docker 将在构建期间忽略这些文件夹/文件。

更新

您可以docker-compose.yml在根目录中包含文件,查看docker-compose以获取所有选项,例如设置environment、运行特定命令等,您可以在构建过程中使用这些选项。

version: "3"
services:
  microservice1:
    build:
      context: .
      dockerfile: ./microservice1/Dockerfile
    volumes:
      - "./path/to/share:/path/to/mount/on/container"
    ports:
      - "<host>:<container>"
    links:
      - rootservice # defines a dns record in /etc/hosts to point to rootservice
  microservice2:
    build:
      context: .
      dockerfile: ./microservice2/Dockerfile
    volumes:
      - "./path/to/share:/path/to/mount/on/container"
    ports:
      - "<host>:<container>"
    links:
      - rootservice # defines a dns record in /etc/hosts to point to rootservice
      - microservice1
  rootservice:
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      - "./path/to/share:/path/to/mount/on/container"
    ports:
      - "<host>:<container>"
    depends_on:
      - microservice1
      - microservice2
    ports:
      - "<host1>:<container1>"
      - "<host2>:<container2>"
Run Code Online (Sandbox Code Playgroud)

这将是您的构建配方microservices,您现在可以运行docker-compose build以构建所有图像。


Dav*_*aze 5

如果您拥有的唯一工具是 Docker,那么选择就不多了。关键问题是只有一个.dockerignore文件。这意味着您始终必须使用项目根目录作为 Docker 上下文目录(包括每个服务的源代码),但您可以告诉 Docker 要使用其中的哪个特定 Dockerfile。(请注意,在本例中,所有COPY指令都与 相关rootFolder。)

docker build rootFolder -f microservice1/Dockerfile -t micro/service1:20190831.01
Run Code Online (Sandbox Code Playgroud)

在许多语言中,都有一种打包库的方法(C .a.h.so文件;Java.jar文件;Python 轮子;...)。如果您的语言支持这一点,另一种选择是构建库,然后将库复制(而不是符号链接)到每个服务的构建树中。以Python的wheel格式为例:

pip wheel ./lib
cp microlib.whl microservice1
docker build microservice1 -t micro/service1:20190831.01
# Dockerfile needs to
# RUN pip install ./microlib.whl
Run Code Online (Sandbox Code Playgroud)

另一个有用的变体是手动多阶段构建。您可以lib/Dockerfile选择一些基础映像,然后将库安装到该基础映像中。然后每个服务都会Dockerfile启动FROM库映像并预安装它。以 C 库为例:

# I am lib/Dockerfile

# Build stage
FROM ubuntu:18.04 AS build
RUN apt-get update && apt-get install build-essential
WORKDIR /src
COPY ./ ./
RUN ./configure --prefix=/usr/local && make
# This is a typical pattern implemented by GNU Autoconf:
# it actually writes files into /src/out/usr/local/...
RUN make install DESTDIR=/src/out

# Install stage -- service images are based on this
FROM ubuntu:18.04
COPY --from=build /src/out /
RUN ldconfig
Run Code Online (Sandbox Code Playgroud)
# I am microservice1/Dockerfile
ARG VERSION=latest
FROM micro/lib:${VERSION}
# From the base image, there are already
# /usr/local/include/microlib.h and /usr/local/lib/libmicro.so
COPY ...
RUN gcc ... -lmicro
CMD ...
Run Code Online (Sandbox Code Playgroud)

通常还有一个选项(同样,取决于您的语言及其打包系统)将您构建的库上传到某个服务器,可能是您自己运行的服务器。(例如,Python piprequirements.txt文件可以包含轮子的任意 HTTP URL。)如果您这样做,那么您可以将您的库声明为普通依赖项,这个问题就会消失。

其中哪一个更适合您取决于您​​的语言和运行时,以及docker build您愿意执行的多个协调命令的自动化程度。