docker自制镜像静态编译
① 如何在"特殊"的网络环境下编译 Docker
由于 Docker 编译需要依赖于 Docker Daemon ,所以只能在 64 位的 linux 环境下先安装 Docker 程序,再从 Github 上克隆 Docker 的代码进行编译。
在 Docker 的目录下执行 make 命令将默认执行 Makefile 中 make binary 指令进行编译。
?
default: binary
all: build
$(DOCKER_RUN_DOCKER) hack/make.sh
binary: build
$(DOCKER_RUN_DOCKER) hack/make.sh binary
cross: build
$(DOCKER_RUN_DOCKER) hack/make.sh binary cross
从以上的 Makefile 可以看出,执行 make、make binary、make all 或 make cross 都可以得到可运行的 Docker 程序。
在 Mac OS 环境下使用 brew 的命令安装 Docker ,只能得到一个 docker client 的二进制程序,如果以 daemon 的方式运行,会得到 ‘This is a client-only binary - running the Docker daemon is not supported.’ 的错误提示信息。
方法 1.
使用 VirtualBox 或者 VMWare Workstation 安装一个 Linux 的虚拟机。宿主机使用 VPN 等方案使网络“正常”访问各种“服务”,虚拟机网卡使用 NAT 模式。在 Linux 虚拟机内使用 make 进行编译 Docker 不会有任何网络问题。只是编译速度受限于 VPN 等网络解决方案,有可能等待时间很长。
方法 2.
Docker 每次发布新版本,都会在 docker-dev 的镜像仓库发布一个新的标签,这个镜像仓库包含了编译 Docker 镜像所依赖的所有环境,只需替换 Docker 代码目录下的 Dockerfile 即可实现编译 Docker 。
?
FROM docker.cn/docker/docker-dev:v1.2.0
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor selinux
ENTRYPOINT [“hack/dind”]
COPY . /go/src/github.com/docker/docker
Dockerfile 中只保留必要的步骤就可以实现编译了。
方法 3.
对 Docker 代码中的 Docker 进行彻底的改造,用国内的各种镜像替换其中不能在“正常”网络条件下访问的镜像,使得代码能够快速编译通过。
?
FROM docker.cn/docker/ubuntu:14.04.1
MAINTAINER Meaglith Ma <[email protected]> (@genedna)
RUN echo "deb http://mirrors.aliyun.com/ubuntu trusty main universe" > /etc/apt/sources.list && echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted" >> /etc/apt/sources.list && echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted" >> /etc/apt/sources.list && echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted" >> /etc/apt/sources.list && echo "deb http://mirrors.aliyun.com/ubuntu/ trusty universe" >> /etc/apt/sources.list && echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty universe" >> /etc/apt/sources.list && echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-updates universe" >> /etc/apt/sources.list && echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates universe" >> /etc/apt/sources.list && echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted" >> /etc/apt/sources.list && echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted" >> /etc/apt/sources.list && echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-security universe" >> /etc/apt/sources.list && echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
btrfs-tools \
build-essential \
curl \
dpkg-sig \
git \
iptables \
libapparmor-dev \
libcap-dev \
libsqlite3-dev \
lxc=1.0* \
mercurial \
parallel \
reprepro \
ruby1.9.1 \
ruby1.9.1-dev \
s3cmd=1.1.0* \
unzip \
--no-install-recommends
RUN git clone --no-checkout https://coding.net/genedna/lvm2.git /usr/local/lvm2 && cd /usr/local/lvm2 && git checkout -q v2_02_103
RUN cd /usr/local/lvm2 && ./configure --enable-static_link && make device-mapper && make install_device-mapper
RUN curl -sSL http://docker-cn.qiniudn.com/go1.3.1.src.tar.gz | tar -v -C /usr/local -xz
ENV PATH /usr/local/go/bin:$PATH
ENV GOPATH /go:/go/src/github.com/docker/docker/vendor
ENV PATH /go/bin:$PATH
RUN cd /usr/local/go/src && ./make.bash --no-clean 2>&1
ENV DOCKER_CROSSPLATFORMS \
linux/386 linux/arm \
darwin/amd64 darwin/386 \
freebsd/amd64 freebsd/386 freebsd/arm
ENV GOARM 5
RUN cd /usr/local/go/src && bash -xc 'for platform in $DOCKER_CROSSPLATFORMS; do GOOS=${platform%/*} GOARCH=${platform##*/} ./make.bash --no-clean 2>&1; done'
RUN mkdir -p /go/src/github.com/gpmgo \
&& cd /go/src/github.com/gpmgo \
&& curl -o gopm.zip http://gopm.io/api/v1/download?pkgname=github.com/gpmgo/gopm\&revision=dev --location \
&& unzip gopm.zip \
&& mv $(ls | grep "gopm-") gopm \
&& rm gopm.zip \
&& cd gopm \
&& go install
RUN gopm bin -v code.google.com/p/go.tools/cmd/cover
RUN gem sources --remove https://rubygems.org/ \
&& gem sources -a https://ruby.taobao.org/ \
&& gem install --no-rdoc --no-ri fpm --version 1.0.2
RUN gopm bin -v -d /go/bin github.com/cpuguy83/go-md2man@tag:v1
RUN git clone -b buildroot-2014.02 https://github.com/jpetazzo/docker-busybox.git /docker-busybox
RUN /bin/echo -e '[default]\naccess_key=$AWS_ACCESS_KEY\nsecret_key=$AWS_SECRET_KEY' > /.s3cfg
RUN git config --global user.email '[email protected]'
RUN groupadd -r docker
RUN useradd --create-home --gid docker unprivilegeser
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor selinux
ENTRYPOINT ["hack/dind"]
COPY . /go/src/github.com/docker/docker
以上的命令把 Ubuntu 镜像中的源替换为国内速度较快的阿里源;把 lvm2 镜像到国内的 Git 托管服务 coding.net;从 七牛云存储 保存的 Golang 源码进行获取和编译;使用 gopm 下载编译所需要的 Library ;最后把其中 gem 源切换到淘宝。至此,可以在“特殊”的网络条件下快速编译 Docker 。
② 构建Docker镜像应该遵循哪些原则
整体远侧上,尽量保持镜像功能的明确和内容的精简,要点包括:
(1)尽量选取满足需求但较小的基础系统镜像,建议选择debian:wheezy镜像,仅有86MB大小
(2)清理编译生成文件、安装包的缓存等临时文件
(3)安装各个软件时候要指定准确的版本号,并避免引入不需要的依赖
(4)从安全的角度考虑,应用尽量使用系统的库和依赖
(5)使用Dockerfile创建镜像时候要添加.dockerignore文件或使用干净的工作目录
我推荐你去看看时速云,他们是一家全栈云原生技术服务提供商,提供云原生应用及数据平台产品,其中涵盖容器云PaaS、DevOps、微服务治理、服务网格、API网关等。大家可以去体验一下。 如果我的回答能够对您有帮助的话,求给大大的赞。
③ aria2 编译docker
docker的编译环境实际上是创建一个docker容器,在容器中对代码进行编译。
操作方法:
1.在dockerHub上注册一个共有账户。
2.编译系统下(假设ubuntu)安装docker,并登录hub账户。
3.编译系统下创建一个docker镜像,安装并调试好aria2。
4.镜像保存好后,就可以将本地docker镜像推送到hub上了。
5.通过dockerhub,大家就可以直接pull你的aria2镜像了。
④ docker镜像构建
基本的构建命令为: docker build -t name:tag -f Dockerfile .
-t : 表示构建出来的镜像名称
-f : 表示构建使用的dockerfile文件名称
. : 表示构建使用当前路径作为上下文(contex),如果你是在根目录 / 下面构建,不建议使用 . (不建议使用根路径作为上下文),因为根路径下面有虚拟文件系统,如 /proc 之类的,构建的时候会报找不到文件的错误。
镜像构建流程为首先将指定的上下文(contextpath)路径下的文件打包,发送到服务端。服务端再将收到的文件解压,然后以解压后的路径作为上下文,进行镜像构建。
docker构建命令中如果没有以 -f 指定Dockerfile,则以上下文中的Dockerfile文件作为构建文件;如果通过 -f 指定了Dockerfile文件路径及名称,则在构建上下文中寻找指定的文件。
docker build的时候,如果某一层无法使用上一次的构建缓存,则后续层均无法使用,故若大多数层均未改变,建议将未改动的层放在前面。如 RUN apt get install -y tmux 命令,如果tmux版本有变化,则无法继续使用构建缓存,建议将该语句放到后面。
参考: https://blog.orenoid.com/2019/12/17/docker-build-optimize/ 。
--no-cache=true 可以不使用缓存,不知道能否解决构建时提示缓存不足的问题。
可以直接编译得到最终镜像: docker build -t go/helloworld:3 .
也可以只构建 builder 阶段的镜像: docker build --target builder -t username/imagename:tag .
构建时,可以复制上一阶段的镜像中的文件,也可以复制任意镜像中的文件。
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
as 后面的名字可以任意填写,主要作用是作为一个标识,方便单独构建其中一个镜像,或者是其他镜像从中获取部分文件。
参考: https://yeasy.gitbook.io/docker_practice/image/multistage-builds/laravel
没有守护进程,不需要 root 特权,而且生成的是符合 OCI 的镜像,因此你的镜像的运行方式与使用 Docker 构建的镜像完全相同。它还能使用 Dockerfile 或 Containerfile 构建镜像, Dockerfile 与 Containerfile 实际上是同一个东西,只是叫法不同罢了。除此之外,Buildah 还提供了对镜像层更精细的控制,支持提交大量的变更到单个层。我认为,它与 Docker 之间有一个出乎意料的区别(但这个区别是好事),那就是使用 Buildah 构建的镜像特定于用户,因此你可以只列出自己构建的镜像。
Google 发布了“ Kaniko ”,一种用于在未授权容器或 Kubernetes 集群中构建容器镜像的开源工具。虽然 Kaniko 也是根据用户给定的 Dockerfile 构建镜像,但是并不依赖于 Docker 守护进程,而是在用户空间中完全执行每个命令,并对所导致的文件系统更改做快照。一般多用于在流水线中执行的编译构建。它与 Buildah 的主要区别在于,Kaniko 更加侧重于 Kubernetes 中的镜像构建。
另外需要制定镜像仓库名字,从而自动推送到目标仓库。
--context :指定构建上下文(可以挂载本地目录,也可以指定git地址,如 git://github.com/mycorp/my-app.git ),
--destination :指定要推送的仓库地址,
--dockerfile :指定dockerfile文件。存在一个问题是,tag是写死的,每次得到的镜像会覆盖。
k8s中使用: https://segmentfault.com/a/1190000039713484
并行构建、跳过未使用的阶段、更好的增量构建以及不需要 root 权限等构建。但是,它仍然需要运行守护进程 (buildkitd)。因此,如果你不想摆脱 Docker,同时又想要一些新的功能和改进,那么可以考虑一下 buildkit。
⑤ 如何用Dockerfile创建镜像
创建镜像:
1、准备jdk、需要运行的spring boot小项目
将jdk压缩包解压到Dockerfile所在的目录中,将spring boot小项目websocket.jar复制到Dockerfile所在的目录下:
⑥ docker如何制作自己的镜像
准备一个用来制作镜像的容器。这里我们使用 centos 安装 apache 的容器。容器的制作方法如下
操作步骤如下:
语法如下:
示例如下:
使用 docker build 创建镜像时,需要使用 Dockerfile 文件自动化制作镜像。 Dockerfile 的执行过程,很像源码编译时 ./configure 后产生的 Makefile 。
这里将镜像发布到 hub.docker.com ,docker的官方仓库。
⑦ docker能否基于已有的rabbitmq镜像制作自已的镜像
完全可以的。
Docker提供了自行开发镜像的功能,可能你需要使用Dockerfile
你可以通过Dockerfile,以rabbitmq:management为基础Image,然后通过修改entrypoint文件,添加运行你的程序的命令即可。
然后通过Docker build 命令来生成自己的Image
最后调用docker run命令来启动容器,查看结果。
⑧ 如何用Dockerfile创建镜像
制作镜像的方式主要有两种:
通过docker commit 制作镜像
通过docker build 制作镜像
这两种方式都是通过改进已有的镜像来达到自己的目的。制作基础镜像,会在另外一篇文章“从零开始制作基础镜像”中介绍。
docker commit
docker commit 是往版本控制系统里提交一次变更。使用这种方式制作镜像,本质上是运行一个基础镜像,然后在基础镜像上进行软件安装和修改。最后再将改动提交到版本系统中。
⑨ 如何使用docker来制作我现在正在使用的系统的镜像
在使用Docker的过程中,我们除了从Docker Hub上下载已经做好的镜像,很多时候需要我们自己制作镜像。下面想在这个文章中说明一下镜像的制作方法。
制作镜像的方式主要有两种:
通过docker commit 制作镜像
通过docker build 制作镜像
这两种方式都是通过改进已有的镜像来达到自己的目的。制作基础镜像,会在另外一篇文章“从零开始制作基础镜像”中介绍。
docker commit
docker commit 是往版本控制系统里提交一次变更。使用这种方式制作镜像,本质上是运行一个基础镜像,然后在基础镜像上进行软件安装和修改。最后再将改动提交到版本系统中。
选择基础镜像
基础镜像的选择要结合自己的需求。可以选择已有的应用镜像来改造,也可以选择Ubuntu,Debian,OpenSuse这类基础系统镜像
我们以ubuntu为例子来说明
步骤1:运行ubuntu 镜像
docker run -i -t ubuntu /bin/bash
步骤2:安装软件并修改软件配置, 比如:安装apache2
apt-get -yqq update
apt-get -y install apache2
安装完成后,对apache2进行配置和修改
步骤3:退出docker并保存镜像
使用“exit”命令退出容器
运行docker comit 命令, 进行保存
docker commit 61412230ae46 own-apache2
docker commit 命令参数说明
命令格式
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
OPTIONS:
-a, --author= 提交的镜像作者
-c, --change=[] Apply Dockerfile instruction to the created image, 没用过
-m, --message= 提交时的说明文字
-p, --pause=true 在commit时,将container 暂停
CONTAINER:
可以使用container 的名字或者ID
REPOSITORY
指定镜像仓库,上述例子中,指定的是本地存储
可以指定远程镜像仓库,如docker hub。也可自建仓库来存放image
TAG:
镜像TAG
docker build
使用docker build创建镜像需要编写Dockerfile.
步骤:
编写自己的Dcokerfile
运行docker build 命令打包镜像
仍然以apache打包为例子。以下是Dockerfile的例子
FROM ubuntu:latest
MAINTAINER sky
#Add 163 mirror for apt
ADD sources.list /etc/apt/sources.listADD .bashrc /root/.bashrcENV DEBIAN_FRONTEND noninteractive# PackagesRUN rm -rf /var/lib/apt/listsRUN apt-get update -q --fix-missingRUN apt-get -y upgrade#ubuntu wwwRUN apt-get install -y apache2 curl libapache2-mod-php5 php5-curl php5-gd php5-mysql rsync mysql-client -qqRUN apt-get autocleanRUN rm -rf /var/lib/apt/lists/*# Setup environmnt for apache's init scriptENV APACHE_CONFDIR /etc/apache2ENV APACHE_ENVVARS $APACHE_CONFDIR/envvarsENV APACHE_RUN_USER www-dataENV APACHE_RUN_GROUP www-dataENV APACHE_RUN_DIR /var/run/apache2ENV APACHE_PID_FILE $APACHE_RUN_DIR/apache2.pidENV APACHE_LOCK_DIR /var/lock/apache2ENV APACHE_LOG_DIR /var/log/apache2ENV LANG CRUN mkdir -p $APACHE_RUN_DIR $APACHE_LOCK_DIR $APACHE_LOG_DIRRUN find "$APACHE_CONFDIR" -type f -exec sed -ri ' \ s!^(\s*CustomLog)\s+\S+!\1 /proc/self/fd/1!g; \ s!^(\s*ErrorLog)\s+\S+!\1 /proc/self/fd/2!g; \' '{}' ';'EXPOSE 80CMD ["apache2", "-DFOREGROUND"]
编辑完成后,在与Dockerfile同一目录下运行docker build 命令
docker build -t apache-img .
如果没有命令出错,docker build会持续运行直到镜像创建完成
而创建的过程本质上是运行一个镜像,然后在镜像中按序执行在Dockerfile中的命令,直到执行结束。
如果中间有命令执行失败,镜像创建会停止。这时就需要看log,并修改Dockerfile,然后再次执行docker build
注:两种镜像创建方式的对比:
docker commit
docker build
难度相对容易,适合新手和对Linux不熟悉的用户相对难,要求有一定的linux和脚本基础知识
文档化
文档化在通过其他文件来实现
Dockerfile本身就是比较好的文档,可读和可理解性比较强。也可配合其他文档带来详细说明
升级,维护
后续升级和维护麻烦,需要再次运行镜像并对内部软件进行升级或者安装新软件增加特性
后续升级和维护会相对简单,可以直接在dockerfile中更改并增加新特性
具体选择哪种方式来制作镜像需要结合实际情况来选择
Dockerfile 关键字详解
FROM
FROM用来指定基础包。在上面的例子中,基础包用的是ubuntu。
MAINTAINER
镜像作者信息,或者维护人员信息
ADD
将文件拷贝到Container内文件系统对应的路径
格式 ADD <src file> <dst file>
所有拷贝到Container中的文件和文件夹权限为0755,uid和gid为0
如果需要修改owner用户或者权限,需要使用RUN进行修改
ADD文件,文件路径要在docker build<PATH>中指定的<PATH>下
RUN
创建镜像时执行
ENV
用来设置环境变量
EXPOSE
Container内部服务开启的端口
主机上如果要使用,还需要在启动Container时,做host-container的商品映射
使用EXPOSE后,一些自动化布署工具可以直接读取这个信息,自动进行端口映射
EXPOSE可以有多条,指定多个端口
WORKDIR
切换工作目录,可进行多次切换(相当于cd命令)
切换目录对RUN,CMD,ENTRYPOINT有效
USER
执行container的用户,如未指定,则默认使用root用户
ENTRYPOINT
Container启动时执行的命令,一个Dockerfile中只能有一条ENTRYPOINT
ENTRYPOINT没有CMD的可替换特性
CMD
Container 启动时执行的命令,一个Dockerfile 中只能有一条CMD命令,如果有多条则只执行最后一条CMD
如果有多条命令希望在启动后执行,可以考虑使用shell 脚本
与ENTRYPOINT的区别
CMD的主要用途是为可执行的container提供默认命令
CMD在运行时是可替换的,比如
在ubuntu中,CMD指定的是/bin/bash。默认情况下运行ubuntu,container中的/bin/bash会被执行
如果使用docker run指定运行命令,那CMD会被替换掉
如:docker run ubuntu /bin/echo "this is a echo". 这时,container 启动后会执行echo 而不是/bin/bash了
ENTRYPOINT是不会替换的,如果在ubuntu镜像中加入ENTRYPOINT,那ENTRYPOINT在启动后会先被执行
CMD可以为ENTRYPOINT来提供参数
例子:
FROM ubuntu:14.10
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
VOLUME
语法:VOLUME [PATH]
VOLUME指令用来设置一个挂载点,可以用来让其他容器挂载以实现数据共享或对容器数据的备份、恢复或迁移
可以将本地文件夹或者其他Container的文件夹挂载到Container中
⑩ Docker镜像
1.像一个文件联合系统UnionFS,是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
3.镜像分层的好处就是资源共享
列如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
4.docker 镜像都是只读的,当容器启动时,一个新的可写层会加载到镜像的顶部,这一层被称为容器层,容器层之下都称为镜像层。
5.镜像的构建可以通过 Dockfile 和docker commit 这两种方式
docker commit 方式是在一个镜像的基础上,重新对该镜像操作后重新生成的一个专属的镜像。
命令格式 docker commit -m "提交的描述信息" -a "作者信息" 容器ID 要创建的目标的镜像名:[标签名]
示例