Using Custom-Built Docker Images

This document describes how to create and use custom Docker images with CircleCI in the following sections:

概要

Circleci.supports Docker, providing you with a powerful way to specify dependencies for your projects. If theCircleci.convenience images不适合您的需求,考虑为您创建自定义Docker图像。这样做有两个主要好处:

  • 更快的工作执行 -将所需工具包装到自定义图像中删除每项工作安装它们的需要。

  • Cleaner configuration –将冗长的安装脚本添加到自定义图像中减少了您的行数config.yml.文件。

注意:When building Docker images, CircleCI does not preserve entrypoints by default. See添加entrypoint.for more details.

Circleci dockerfile巫师

Refer to thedockerfile巫师Circleci公众的GitHub存储库有关克隆的说明并使用向导创建Dockerfile以在不安装Docker的情况下生成自定义图像。

Creating a Custom Image Manually

的following sections provide a walkthrough of how to create a custom image manually. In most cases you’ll want to have a custom image for your主要容器这是本文档的重点。但是,您可以轻松应用此知识,以创建用于支持容器的图像。

Prerequisite

Creating adockerfile.

要创建自定义图像,必须创建一个dockerfile.。这是包含Docker用于组装图像的命令的文本文档。考虑保留你的dockerfile.在你的。Circleci./images文件夹,如图所示this Docker demo project

Choosing and Setting a Base Image

在创建自定义图像之前,必须选择从中选择要扩展自定义图像的其他映像。Docker Hub.has official, pre-built images for most popular languages and frameworks. Given a particular language or framework, there are many image variants from which to choose. These variants are specified byDocker tags

For example, if you want to use version 3.5 of the官方高山形象, the full image name is高山:3.5

In yourdockerfile.,通过使用延伸基础图像instruction

从golang:1.8.0

Installing Additional Tools

要安装任何其他工具或执行其他命令,请使用instruction

运行apt-get更新&& apt-get安装-y netcat运行go get github.com/jstemmer/go-junit-report

主要容器的必需工具

要用作Circleci上的主要容器,自定义Docker映像必须安装以下工具:

Without these tools, some CircleCI services may not work.

注意:如果没有使用包管理器安装这些工具,则必须使用ADD指令而不是(see below).

添加其他文件和目录

添加包管理器中不存在的文件和目录,请使用ADDinstruction

添加./workdir/contacts / usr / bin / contacts添加./db/migrations /迁移

添加entrypoint.

要将容器运行为可执行文件,请使用ENTRYPOINTinstruction。默认情况下,Circleci将忽略作业主容器的入口点。即使图像用于主容器,也要保留入口点,请使用标签instructionas shown below.

标签com.circleci.preve-entrintpoint =真正的入口点联系人

注意:Entrypoints should be commands that run forever without failing. If the entrypoint fails or terminates in the middle of a build, the build will also terminate. If you need to access logs or build status, consider using a background step instead of an entrypoint.

Building the Image

在所有所需工具中指定dockerfile.it is possible to build the image.

$Docker构建

您将看到所有指定的命令dockerfile.被执行。如果他们会显示任何错误,并且您需要在继续之前修复它们。如果构建成功,您将在最终中有这样的东西:

...成功构建了e32703162dd4

阅读更多信息docker build命令

Congratulations, you’ve just built your first image! Now we need to store it somewhere to make it available for CircleCI.

Storing Images in a Docker Registry

为了允许Circleci使用自定义图像,将其存储在公共场所Docker Registry。最简单的机制是创建一个帐户Docker Hub.因为Docker Hub允许您免费存储无限的公共图像。如果您的组织已经使用Docker Hub,您可以使用现有帐户。

注意:To use an image with the CircleCIDocker Executor您必须有一个公共存储库。如果要保留您的图像私密,请参阅Using Docker Authenticated Pulls文档有关说明。

的example uses Docker Hub, but it is possible to use different registries if you prefer. Adapt the example based on the registry you are using.

为注册表准备图像

使用您的帐户登录Docker Hub并在此处创建新的存储库添加存储库页。使用类似的模式是最好的做法 - <容器名称>for a repository name (for example,cci-demo-docker-primary).

接下来,使用您的帐户和存储库名称重建图像:

$ docker build -t circleci / cci-demo-docker-primary:0.0.1 

-T.key specifies the name and tag of the new image:

  • Circleci.- our account in Docker Hub
  • cci-demo-docker-primary- 存储库名称
  • 0.0.1- tag (version) of the image. Always update the tag if you change something in adockerfile.否则您可能有不可预测的结果。

将图像推到注册表

将图像推到Docker Hub:

$ docker登录$ docker push circleci / cci-demo-docker-might:0.0.1

注意:首先,我们使用docker登录在Docker Hub中进行身份验证。如果使用Docker Hub以外的注册表,请参阅有关如何将图像推送到该注册表的相关文档。

在Circleci上使用您的图像

成功推动图像后,它可以使用它。Circleci./config.yml:

版本:2.0作业:Build:Docker: - 图片:Circleci / CCI-Demo-Docker-Primary:0.0.1 auth:用户名:MyDockerHub-User密码:$ Dockerhub_password#上下文/项目UI Env-Var参考

If you have any questions, head over to ourcommunity forumfor support from us and other users.

Ruby的详细自定义dockerfile示例

This section demonstrates how to build a Ruby container to use on CircleCI 2.0.注意:This section assumes you have already used docker login locally.

该示例始于Ruby 2.1.图片。但是,而不是使用Ruby:2.1作为基础图像,它描述了如何构建容器。从Ruby Docker Hub页面,转到2.1/Dockerfile。Notice the environment variables that are used to pull in the proper versions.

来自BuildPack-Deps:Jessie #skip安装宝石文档运行Mkdir -p / usr / local / local / etc \ && {\ echo'安装:--no-document';\ echo'更新:--no-document';\} >> / usr / local / etc / gemrc env Ruby_major 2.1 env Ruby_download_sha256 5be9f8d5d29d2562cd7f969ab7550e31bbb001c7550e31bbb001c0d252cd7f969ab7550e31bbb001c0b4a83532301c0dd3b5006e148 env ruby​​gems_version 2.6.10#ruby的构建脚本是用ruby#我们稍后清除系统Ruby以确保我们的最终图像使用我们刚刚构建的运行set -ex \ \ && builddeps ='\ bison \ libgdbm-dev \ ruby​​ \'&& apt-get update \ && apt-get安装-y --no-install-mechants $ builddeps \ &&rm -rf / var / lib / apt / lists / * \&&& wget -o ruby​​.tar.xz“https://cache.ruby-lang.org/pub/ruby/$(ruby_major%-rc)/ ruby-  $ ruby​​_version.tar.xz“\ && echo”$ ruby​​_download_sha256 * ruby​​.tar.xz“|SHA256SUM -C-\ \ && MKDIR -P / USR / SRC / RUBY \ && tar -xjf ruby​​.tar.xz -c / usr / src / ruby​​ --strip-components = 1 \ && rm ruby​​.tar.xz \\ && cd / usr / src / ruby​​ \ \ #hack在“enable_path_check”中禁用抑制:#警告:不安全的世界可写dir && {\ echo'#define enable_path_check 0';\ echo;\ cat文件;\}> file.c.new \ && mv file.c.new file.c \ && && autoconf \ && && ./configure  -  dis-install-doc-enable-shared \ && make -j“$(nproc)" \ && make install \ \ && apt-get purge -y --auto-remove $buildDeps \ && cd / \ && rm -r /usr/src/ruby \ \ && gem update --system "$RUBYGEMS_VERSION" ENV BUNDLER_VERSION 1.14.3 RUN gem install bundler --version "$BUNDLER_VERSION" # install things globally, for great justice # and don't create ".bundle" in all our apps ENV GEM_HOME /usr/local/bundle ENV BUNDLE_PATH="$GEM_HOME" \ BUNDLE_BIN="$GEM_HOME/bin" \ BUNDLE_SILENCE_ROOT_WARNING=1 \ BUNDLE_APP_CONFIG="$GEM_HOME" ENV PATH $BUNDLE_BIN:$PATH RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \ && chmod 777 "$GEM_HOME" "$BUNDLE_BIN" CMD [ "irb" ]

This will create a Ruby 2.1 image. Next, install node modules,awscli,和postgresql 9.5使用节点:7.4 dockerfile:

来自BuildPack-Deps:Jessie Run Groupadd --gid 1000节点\ && useradd  -  uid 1000 --gid节点 -  shell / bin / bash -create-home节点#gpg键在https://github.com/处列出的NodeJS /节点RUN组-ex \ &&为键在\ 9554F04D7259F04124DE6B476D5A82AC7E37093B \ 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ 0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \ FD3A5288F042B6850C66B31F09FE44734EB7990E \ 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ B9AE9905FFD7803F25714661B63B535A4C206CA9 \ C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \;do \ gpg --keyserver ha.pool.sks-keyservers.net --recv-keys“$ key”;\ done env npm_config_loglevel info env node_version 7.4.0运行curl -slo“https://nodejs.org/dist/vrnode_version/node-v whernode_version-linux-x64.tar.xz”\ && curl -slo“https://nodejs.org/dist/vhrnode_version/shasums256.txt.asc“\ && gpg  - 斑点--decrypt --output shasums256.txt shasums256.txt.asc \ && grep”node-v $ node_version-linux-x64.tar.xz \ $“shasums256.txt |sha256sum -c-\ && tar -xjf“node-v $ node_version-linux-x64.tar.xz”-c / usr / local --strip-components = 1 \ && rm“node-v $ node_version-linux-x64.tar.xz“shasums256.txt.asc shasums256.txt \ && ln -s / usr / local / bin / node / usr / local / bin / nodejs cmd [”node“]

两个dockerfiles都使用相同的基础图像buildpack-deps:jessie。This is excellent because it is possible to combine them and install Python to getawscli

通过使用之前删除关联的文件,然后才能使用Docker映像安装易于。可以安装所有内容并以后删除这些文件,但不运行易于-get update不止一次。任何自定义重播都是事先添加的。

Ruby Image附带Git预装,因此没有理由重新安装它。最后,将sudo,python2.7和postgresql-9.5添加到列表安装列表中。然后,用NPM安装纱线。

来自BuildPack-Deps:Jessie Run Groupadd --gid 1000节点\ && useradd  -  uid 1000 --gid节点 -  shell / bin / bash -create-home节点#gpg键在https://github.com/处列出的NodeJS /节点RUN组-ex \ &&为键在\ 9554F04D7259F04124DE6B476D5A82AC7E37093B \ 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ 0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \ FD3A5288F042B6850C66B31F09FE44734EB7990E \ 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ B9AE9905FFD7803F25714661B63B535A4C206CA9 \ C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \;do \ gpg --keyserver ha.pool.sks-keyservers.net --recv-keys“$ key”;\ done env npm_config_loglevel info env node_version 7.4.0 envern_version 0.18.1运行curl -slo“https://nodejs.org/dist/vrnode_version/node-v whernode_version-linux-x64.tar.xz”\ &&curl -slo“https://nodejs.org/dist/vrnode_version/shasums256.txt.asc”\ && gpg --batch --decrypt --output shasums256.txt shasums256.txt.asc \ && grep“node  -v $ node_version-linux-x64.tar.xz \ $“shasums256.txt |sha256sum -c-\ && tar -xjf“node-v $ node_version-linux-x64.tar.xz”-c / usr / local --strip-components = 1 \ && rm“node-v $ node_version-linux-x64。柏油。xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs # Postgres 9.5 RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main" >> /etc/apt/sources.list \ && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 58118E89F3A912897C070ADBF76221572C52609D 514A2AD631A57A16DD0047EC749D6EEC0353B12C # skip installing gem documentation RUN mkdir -p /usr/local/etc \ && { \ echo 'install: --no-document'; \ echo 'update: --no-document'; \ } >> /usr/local/etc/gemrc ENV RUBY_MAJOR 2.1 ENV RUBY_VERSION 2.1.10 ENV RUBY_DOWNLOAD_SHA256 5be9f8d5d29d252cd7f969ab7550e31bbb001feb4a83532301c0dd3b5006e148 ENV RUBYGEMS_VERSION 2.6.10 # some of ruby's build scripts are written in ruby # we purge system ruby later to make sure our final image uses what we just built RUN set -ex \ \ && buildDeps=' \ bison \ libgdbm-dev \ ruby \ ' \ && apt-get update \ && apt-get install -y --no-install-recommends $buildDeps python2.7 sudo postgresql-9.5 \ && rm -rf /var/lib/apt/lists/* \ \ && wget -O ruby.tar.xz "https://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOR%-rc}/ruby-$RUBY_VERSION.tar.xz" \ && echo "$RUBY_DOWNLOAD_SHA256 *ruby.tar.xz" | sha256sum -c - \ \ && mkdir -p /usr/src/ruby \ && tar -xJf ruby.tar.xz -C /usr/src/ruby --strip-components=1 \ && rm ruby.tar.xz \ \ && cd /usr/src/ruby \ \ # hack in "ENABLE_PATH_CHECK" disabling to suppress: # warning: Insecure world writable dir && { \ echo '#define ENABLE_PATH_CHECK 0'; \ echo; \ cat file.c; \ } > file.c.new \ && mv file.c.new file.c \ \ && autoconf \ && ./configure --disable-install-doc --enable-shared \ && make -j"$(nproc)" \ && make install \ \ && apt-get purge -y --auto-remove $buildDeps \ && cd / \ && rm -r /usr/src/ruby \ \ && gem update --system "$RUBYGEMS_VERSION" ENV BUNDLER_VERSION 1.14.3 RUN gem install bundler --version "$BUNDLER_VERSION" RUN npm install -g yarn@0.18.1 ENV PATH "$PATH:/root/.yarn/bin/:/usr/local/bin" # install things globally, for great justice # and don't create ".bundle" in all our apps ENV GEM_HOME /usr/local/bundle ENV BUNDLE_PATH="$GEM_HOME" \ BUNDLE_BIN="$GEM_HOME/bin" \ BUNDLE_SILENCE_ROOT_WARNING=1 \ BUNDLE_APP_CONFIG="$GEM_HOME" ENV PATH $BUNDLE_BIN:$PATH RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \ && chmod 777 "$GEM_HOME" "$BUNDLE_BIN" CMD [ "irb" ]

要构建它,请运行以下命令:

docker build -t ruby-node:0.1 .

完成后,它应该显示以下内容:

卸下中间容器E75339607356成功构建了52b773cf50e2

After it finishes compiling, take the sha from the Docker output and run it as follows:

$ docker运行-it 52b773cf50e2 / bin / bash root @ 6cd398c7b61d:/#exit

然后,提交HostName使用Docker Hub用户名替换Ruby-Node,如下所示:

Docker提交6CD398C7B61D用户名/ Ruby-Node:0.1 Docker推送用户名/ Ruby-node:0.1

要使用自定义图像,请参阅Ruby-node / bar:0.1。Circleci./config.ymlimage key and your primary container will run it. It is worth it to commit your Dockerfile using a gist and link to it from Docker Hub to avoid losing your configuration.