1. 概述
Git 是软件开发领域领先的版本控制系统。而 Dockerfile 则包含构建应用程序图像所需的所有命令。这两种产品对于寻求采用 DevOps 的人来说是完美的组合。在这篇教程中,我们将学习一些结合这两种技术的方法。我们将详细讨论每种解决方案及其优缺点。
2. 将 Dockerfile 放入 Git 仓库
在 Dockerfile 直接放入 Git 仓库是最简单的方法,以始终拥有访问 Git 仓库的权限:
ProjectFolder/
.git/
src/
pom.xml
Dockerfile
...
上述设置将使我们能够访问整个项目源目录。接下来,我们可以使用 ADD
命令(请参阅详细信息)将它包含在容器中,例如:
ADD . /project/
当然,我们可以限制复制的范围,仅限于构建目录:
ADD /build/ /project/
或者构建输出如.jar 文件:
ADD /output/project.jar /project/
此解决方案的最大优点是我们可以在不提交到仓库的情况下测试任何代码更改。所有内容都将生活在同一个本地目录中。
这里需要记住的一件事是在 Dockerfile 中创建一个 .dockerignore
文件。它类似于 .gitignore
文件,但在这种情况下,它排除了与其中的模式匹配的文件和目录。这有助于我们避免向 Docker 构建过程发送不必要的大文件或敏感文件,并可能将它们添加到图像中。
3. 克隆 Git 仓库
另一种简单的解决方法是在构建图像过程中仅获取我们的 Git 仓库。我们可以通过简单地将 SSH 密钥添加到本地存储并调用 git clone
命令来实现这一目标:
ADD ssh-private-key /root/.ssh/id_rsa
RUN git clone [email protected]:eugenp/tutorials.git
上述命令将获取整个仓库并将它放置在容器的 ./tutorials
目录中。
不幸的是,这种方法也有一些缺点。
首先,我们将私有 SSH 密钥存储在 Docker 图像中,这可能会带来潜在的安全问题。我们可以通过使用用户名和密码为 Git 仓库应用一个补救措施:
ARG username=$GIT_USERNAME
ARG password=$GIT_PASSWORD
RUN git clone https://username:[email protected]:eugenp/tutorials.git
并将它们作为机器环境变量(请参阅详细信息)。这样我们就可以将 Git 凭据保留在图像之外。
其次,此步骤会在后续构建时缓存,即使我们的仓库发生变化。这是因为带有 RUN
命令的行不变,除非在较早的步骤中破坏缓存。虽然,我们可以通过在 docker build
命令中添加 -no-cache
参数来解决这个问题。
另一个较小的缺点是必须在容器中安装 git 包。
4. 卷映射
我们可以使用的第三个解决方案是 卷映射。它赋予我们从我们的机器挂载目录到 Docker 容器的能力。这是用于存储由 Docker 容器使用的数据的一种首选机制。
我们可以通过在 Dockerfile 中添加以下行来实现这一点:
VOLUME /build/ /project/
这将在容器中创建 /project
目录,并将其挂载到机器上的 /build
目录。
卷映射将是当我们的 Git 仓库仅用于构建过程时的最佳选择。通过将仓库保留在容器之外,我们不会增加其大小,并允许仓库内容超出给定容器的生命周期。
需要记住的一件事是卷映射赋予 Docker 容器对挂载目录的写入权限。不当使用此功能可能导致 Git 仓库目录中出现意外更改。
5. Git 子模块
在将 Dockerfile 和源代码保留在单独的仓库中或我们的 Docker 构建需要多个源仓库的情况下,我们可能会考虑使用 Git 子模块。
首先,我们需要创建一个新的 Git 仓库并将 Dockerfile 放在那里。接下来,我们可以通过将它们添加到 .gitmodules 文件中来定义子模块:
[submodule "project"]
path = project
url = https://github.com/eugenp/tutorials.git
branch = master
现在,我们可以像标准目录一样使用子模块。例如,我们可以将它的内容复制到容器中:
ADD /build/ /project/
请记住,子模块不会自动更新。我们需要运行以下 git 命令以获取最新更改:
git submodule update --init --recursive
6. 概览
在这篇教程中,我们学习了几种在 Dockerfile 中使用 Git 仓库的方法。所有源代码都已 在 GitHub 上提供。