我有由控制台项目,webapi项目和mysql db组成的dotnet解决方案。我将它们放在单独的docker映像中,编写了docker-compose以启动并在我的计算机上进行了测试。接下来,我使用FluentDocker编写了一个测试,该测试允许我以编程方式启动docker-compose并验证容器是否已启动并正在运行。
现在,我想在Gitlab CI上执行此操作。以前,我使用图像:mcr.microsoft.com/dotnet/core/sdk:3.1并对测试项目运行测试阶段。由于没有docker集成,因此工作正常。我无法在Gitlab CI上运行FluentDocker测试,因为该映像不包含docker。所以我开始研究。
将db集成到CI作业中的解决方案在这里https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service,但是我怀疑我可以使用docker作为服务。
下一步是将docker ingration用于gitlabRunner https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor或https://tomgregory.com/running-docker-in-docker-on-windows/ 我不能使用它,因为我使用了来自Gitlab的免费运行程序并无法对其进行配置。我尝试运行docker info命令,但在我的脚本中失败。
我曾考虑过基于包含docker的dotnet sdk构建自己的映像,但这似乎是一个坏主意。我最终没有使它起作用。
似乎可行的解决方案是使用dind并启动docker-compose: How to run docker-compose inside docker in docker which runs inside gitlab-runner container?或 https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30426 但是要使用它,我将需要安装dotnet-sdk来在脚本之前的部分中构建和测试我的应用,并且sdk并不是每次下载的小软件包。
我可以尝试基于docker:dind构建我的映像,并在其中包含dotnet sdk,将其发布在dockerhub上,然后在gitlabRunner中使用它。现在在我看来,这是最后的选择。
那么,这里的正确方法是什么?
-----------编辑--------------
我做到了!请参阅Konrad Botor关于dockerfile和yml文件的非常详尽的答案。我使用sdk和docker构建了自己的映像,并将其用于链接了dind服务的测试阶段。我的映像托管在dockerhub上,因此gitlab下载它以供使用。
还有一些注意事项:
1-如何将Dind用作服务https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25344
2-获取modprobe.sh和docker-entrypoint.sh https://github.com/docker-library/docker的位置(进入最新版本)。非常重要的是从那里克隆repo并复制文件,因为我试图复制粘贴内容,但这没有用。
3-docker-compose仓库https://github.com/tmaier/docker-compose/blob/master/Dockerfile
4-例子https://gitlab.com/gitlab-examples/docker/-/blob/master/.gitlab-ci.yml
答案 0 :(得分:1)
在GitLab示例仓库here中显示了在GitLab CI中使用docker的规范方法。我认为它适用于自由跑步者,因为它是由GitLab自己维护的官方团体。
由于您的工作不仅需要Docker,因此建议您将自定义映像与Dotnet SDK,Docker和docker-compose结合使用,像这样:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
RUN apk add --no-cache \
ca-certificates \
# DOCKER_HOST=ssh://... -- https://github.com/docker/cli/pull/1014
openssh-client
# set up nsswitch.conf for Go's "netgo" implementation (which Docker explicitly uses)
# - https://github.com/docker/docker-ce/blob/v17.09.0-ce/components/engine/hack/make.sh#L149
# - https://github.com/golang/go/blob/go1.9.1/src/net/conf.go#L194-L275
# - docker run --rm debian:stretch grep '^hosts:' /etc/nsswitch.conf
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
ENV DOCKER_CHANNEL stable
ENV DOCKER_VERSION 19.03.12
# TODO ENV DOCKER_SHA256
# https://github.com/docker/docker-ce/blob/5b073ee2cf564edee5adca05eee574142f7627bb/components/packaging/static/hash_files !!
# (no SHA file artifacts on download.docker.com yet as of 2017-06-07 though)
RUN set -eux; \
\
# this "case" statement is generated via "update.sh"
apkArch="$(apk --print-arch)"; \
case "$apkArch" in \
# amd64
x86_64) dockerArch='x86_64' ;; \
# arm32v6
armhf) dockerArch='armel' ;; \
# arm32v7
armv7) dockerArch='armhf' ;; \
# arm64v8
aarch64) dockerArch='aarch64' ;; \
*) echo >&2 "error: unsupported architecture ($apkArch)"; exit 1 ;;\
esac; \
\
if ! wget -O docker.tgz "https://download.docker.com/linux/static/${DOCKER_CHANNEL}/${dockerArch}/docker-${DOCKER_VERSION}.tgz"; then \
echo >&2 "error: failed to download 'docker-${DOCKER_VERSION}' from '${DOCKER_CHANNEL}' for '${dockerArch}'"; \
exit 1; \
fi; \
\
tar --extract \
--file docker.tgz \
--strip-components 1 \
--directory /usr/local/bin/ \
; \
rm docker.tgz; \
\
dockerd --version; \
docker --version
COPY modprobe.sh /usr/local/bin/modprobe
COPY docker-entrypoint.sh /usr/local/bin/
# https://github.com/docker-library/docker/pull/166
# dockerd-entrypoint.sh uses DOCKER_TLS_CERTDIR for auto-generating TLS certificates
# docker-entrypoint.sh uses DOCKER_TLS_CERTDIR for auto-setting DOCKER_TLS_VERIFY and DOCKER_CERT_PATH
# (For this to work, at least the "client" subdirectory of this path needs to be shared between the client and server containers via a volume, "docker cp", or other means of data sharing.)
ENV DOCKER_TLS_CERTDIR=/certs
# also, ensure the directory pre-exists and has wide enough permissions for "dockerd-entrypoint.sh" to create subdirectories, even when run in "rootless" mode
RUN mkdir /certs /certs/client && chmod 1777 /certs /certs/client
# (doing both /certs and /certs/client so that if Docker does a "copy-up" into a volume defined on /certs/client, it will "do the right thing" by default in a way that still works for rootless users)
ENV COMPOSE_VERSION 1.26.2
RUN apk add --no-cache py3-pip python3
RUN apk add --no-cache --virtual build-dependencies python3-dev libffi-dev openssl-dev gcc libc-dev make \
&& pip3 install "docker-compose${COMPOSE_VERSION:+==}${COMPOSE_VERSION}" \
&& apk del build-dependencies
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["sh"]
这基于官方docker:latest
Dockerfile和tmaier/docker-compose:latest
Dockerfile。您还需要第一个存储库中的modprobe.sh
和docker-entrypoint.sh
脚本。
然后按如下所示运行它:
image: docker:latest //whatever image you use in your pipeline most often
variables:
DOCKER_DRIVER: overlay2
stages:
- test
test:
stage: test
image: dotnetsdk-compose:latest //your custom image
services:
- docker:dind
script:
- docker-compose up -d
请注意,新映像基于Alpine 3.12而不是Debian10。如果遇到问题,则必须将上述Dockerfile转换为使用Debian上可用的命令。
答案 1 :(得分:0)
我们公司的情况相同,但是使用了自托管的docker / gitlab等。
当前,我们正在gitlabRunner(您的编号2)中运行docker集成,并且有很多不良影响,例如:gitlabRunner创建的容器未正确清理,因为gitlab-runner不考虑清理,因为在正常情况下,随着docker-runner本身的关闭,它应该(不会)破坏一切。
选项3并不是一件坏事,它是默认且完全正常的事情:我们有一堆docker映像,其中包括lib,这些lib并未随加载的映像一起提供。您已经习惯了-所以我更愿意。是一种干净的解决方案,不会感到“ hacky”。