导出镜像存储: docker save house/redis:3.2 > redis_img.tar (也可以使用镜像ID)
导入镜像存储: docker load < redis_img.tar
导出容器快照: docker export myredis3.2 >myredis.tar (也可以使用容器ID)
以导出的容器快照创建新的镜像: cat myredis.tar | docker import - test/myredis:v1.8 (import---Import the contents from a tarball to create a filesystem image)
导出 export 与 保存 save 的区别:
(1)export导出的镜像文件大小 小于 save保存的镜像
(2)export 导出(import导入)是根据容器拿到的镜像,再导入时会丢失镜像所有的历史,所以无法进行回滚操作(比如:docker tag <LAYER ID> <IMAGE NAME>);而save保存(load加载)的镜像,没有丢失镜像的历史,可以回滚到之前的层(layer)。
import 与 load 的区别:
可以使用 docker import 从容器快照文件中再导入为镜像,如:cat myredis.tar | docker import - test/myredis:v1.8 (个人感觉相比使用docker build更靠谱些)
注:用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。
-----------------------------------------------------------------------------------------
参数形式ARG
这是docker提供的另外一个,让我有点懵逼的命令. 他的实际效果和 ENV
的区别可以趋近于无。
# 使用ARG定义变量
ARG buildno
# 设置默认值
ARG user1=someuser
当然,我们可以在命令中,手动指定替换.
# 在dockerfile定义了默认变量
ARG user=jimy
# 在运行时,进行手动替换
docker build --build-arg user=sam -t jimmy/demo .
上面说了ARG和ENV比较类似,不过,里面的区别还是有的. 即, ARG只能用在 docker build
的阶段, 并且不会被保存在 image
中,这就是和ENV的区别.
-----------------------------------------------------------------------------------------
官网安装步骤:https://docs.docker.com/engine/installation/linux/centos/
一键docker安装命令: curl -fsSL http://get.docker.com | sh (官网)
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun (阿里)
Docker是一个开源的应用容器引擎,开发者可以利用Docker打包自己的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。
Docker是一个能够把开发的应用程序自动部署到容器的开源引擎。
安装docker的先决条件:
- 运行64位CPU架构的计算机,请注意,Docker目前不支持32位CPU
- 运行Linux3.8或更高版本的内核。一些老版本的2.6.x或其后的内核也能够运行Docker,但运行结果会有很大不同。而且,如果你需要就老版本内核寻求帮助时,通常大家会建议你升级到更高版本的内核。
- 内核必须支持一种适合的存储驱动(storeage driver),例如:
Device Manager;
AUFS;
vfs;
btrfs;
默认存储驱动通常是Device Mapper.
- 内核必须支持并开启cgroup和命名空间 (namespace)功能。
----------------------------
检查Device Mapper
# ls -l /sys/class/misc/device-mapper
lrwxrwxrwx 1 root root 0 Mar 8 12:15 /sys/class/misc/device-mapper -> ../../devices/virtual/misc/device-mapper
# grep deice-mapper /proc/devices
如果没有检测到Device Mapper,便开始安装
# yum install -y device-mapper
安装完成后,还需要加载 dm_mod 内核模块
# modprobe dm_mod
# lsmod | grep dm_mod
开始安装docker,前提准备好epel源
# yum -y install docker-io
# service docker start
# docker info (验证)
如果需要修改docker数据根目录的话,vim /etc/sysconfig/docker other_args后面添加--graph参数
other_args='--insecure-registry 10.0.30.5:5000 --graph=/data/docker'
会自动生成/data/docker目录(0700),并在该目录下创建 docker 相关文件
---------------------------------------------------------------------------
docker help run
-i interact交互式,保证容器中STDIN是开启的
-t 它告诉Docker为要创建的窗口分配一个伪tty终端。
这样新创建的容器才能提供一个交互式shell
docker images 查看本地已有的镜像
docker ps 查看当前系统中正运行的容器的列表
docker ps -a 查看当前系统中正运行的和已经停止的容器的列表
docker ps -l 列出最后一次运行的容器,包括正在运行和已经停止的
docker stop wjoyxt 停止守护式容器,删除之前需要先停止正在运行的容器
docker rm wjoyxt 或 docker rm 容器ID 删除一个容器
docker rm `docker ps -a -q` 删除所有容器
docker rmi centos 或 docker rmi 镜像ID 删除一个镜像
docker run --name wjoyxt -i -t centos /bin/bash 为新创建的容器自定义名称,并且容器的命名必须是唯一的。如果创建两相名称相同的容器,则命令将失败。
docker run --name daemon_wjoyxt -d centos /bin/sh -c "while true; do echo hello world;sleep 2;done" 创建长期运行的守护式容器示例
docker create 只是单独地创建一个新的容器,并不运行它
docker start wjoyxt 或 docker start 容器ID 重新启动一个已经停止的容器,会沿用docker run命令时指定的参数来运行
docker attach wjoyxt 或 docker attach 容器ID 重新附着到重新启动的容器的会话上,你可能需要按下回车键才能进入该会话,exit退出后,容器停止运行。
docker logs wjoyxt 获取守护式容器的日志
docker logs -f wjoyxt 跟踪守护式容器的日志,通过Ctrl+C退出日志跟踪
docker logs -ft wjoyxt 使用 -t 标志为每条日志项加上时间戳
docker logs --tail 10 wjoyxt 获取日志的最后10行内容
docker logs --tail 0 -f wjoyxt 跟踪某个容器的最新日志而不必读取整个日志文件
docker top wjoyxt 查看窗口内的进程
docker exec -d wjoyxt touch /etc/new_config_file 在容器中运行后台任务,-d表明运行一个后台进程,后面指定的是要在内部执行这个命令的容器名字以及要执行的命令内容
docker exec -t -i wjoyxt /bin/bash 在wjoyxt容器中启动一个打开shell的交互式任务,exit退出后,容器仍在运行
docker cp jiajia:/etc/haha /root/ 从容器文件系统拷贝文件/目录到宿主机路径
docker inspect wjoyxt 获取容器更详细的相关信息
docker inspect --format='{{ .State.Running }}' wjoyxt 使用-f或者--format标志来选定查看结果。
再例如: docker inspect --f='{{ .Config.Labels.license }}' wjoyxt
docker login 登录到Docker Hub
docker commit 容器ID wjoyxt/mycontainer 创建新的镜像。提交的只是创建容器的镜像与容器的当前状态之间有差异的部分,这使得该更新非常轻量
docker commit -m="A new custom image" --author="wjoyxt" 容器ID wjoyxt/mycontainer:mywebserver 可以在提交镜像时指定更多的数据(包括标签)来详细描述所做的修改
docker build -t="wjoyxt/my_web:v1" . 构建新镜像,使用 -t 设置仓库、镜像和标签名称。(Dockerfile在当前目录下)
docker build --no-cache -t="wjoyxt/my_web" 忽略Dockerfile的构建缓存
docker history 镜像ID 查看镜像的每一层,以及创建这些层的Dockerfile指令
docker run -d -p 8080:80 --name wjoyxt nginx -g "daemon off" -p 将容器中的80端口绑定到宿主机的8080端口上,可以使用docker inspect或 docker port命令来查看容器内的端口具体被绑定到了宿主机的哪个端口上,也可以通过在端口绑定时使用/udp后缀来指定UDP端口
搭建私有仓库: (此方法已过时,请参考本博客的“Docker私有仓库 Registry中的镜像管理”)
docker push wjoyxt/my_web 将镜像推送到Docker Hub
运行自己的Docker Registry:有时候我们可能希望构建和存储包含不想被公开的信息或数据的镜像。这时候我们有两种选择:
- 利用Docker Hub上的私有仓库
- 在防火墙后面运行你自己的Registry
# docker run -d -p 5000:5000 registry 运行基于容器的Registry,并绑定到本地宿主机的5000端口。
默认情况下,会将仓库存放于容器内的/tmp/registry目录下,这样如果运行在registry上的容器被删除,则存放于容器中的镜像也会丢失,所以我们一般情况下会指定本地一个目录挂载到容器内的/tmp/registry下,如下:
或者# docker run -d -p 5000:5000 -v /opt/registry:/tmp/registry registry
<宿主机目录>:<容器目录> 这两个目录会被自动创建好,无需提前创建
(通过-v 参数,冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径。目的是将宿主机的目录作为卷,挂载到容器里。如果目的目录不存在,Docker会自动创建一个)
测试新Registry:
首先找到要上传的镜像的ID,并使用新的Registry给该镜像打上标签。为了指定新的Registry目的地址,需要在镜像名前加上主机名和端口前缀。在这个例子里,我们的Registry主机名为wjoyxt.example.com或者使用IP:
# docker tag 镜像ID 172.16.21.2:5000/wjoyxt/my_web
# docker push 172.16.21.2:5000/wjoyxt/my_web
如果执行以上命令出现以下错误时: vim /etc/sysconfig/docker other_args="--selinux-enabled --insecure-registry 172.16.21.2:5000" 重启Docker服务后即可(本地push端和远程pull端都需要修改,否则都会报以下相同的错误)。
Error response from daemon: invalid registry endpoint https://172.16.21.2:5000/v0/: unable to ping registry endpoint https://172.16.21.2:5000/v0/
v2 ping attempt failed with error: Get https://172.16.21.2:5000/v2/: EOF
v1 ping attempt failed with error: Get https://172.16.21.2:5000/v1/_ping: EOF. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry 172.16.21.2:5000` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/172.16.21.2:5000/ca.crt
这是因为Docker从1.3.X之后,与docker registry交互默认使用的是https,然而此处搭建的私有仓库只提供http服务,所以当与私有仓库交互时就会报上面的错误。为了解决这个问题需要在启动docker server时增加启动参数为默认使用http访问。
为镜像打完标签之后,就能通过docker push命令将它推送到新的Registry中去了。这样就本地局域网内就可以直接使用docker run命令构建新容器了。
# docker search 172.16.21.2:5000/wjoyxt 使用之前可以使用docker search查询一下可使用的仓库镜像
# docker run -it 172.16.21.2:5000/wjoyxt/my_web /bin/bash
关于Docker Registry V2 按上述安装成功后,执行curl -XGET http://172.16.21.2:5000/v2/ 后,页面会出现一个{}符号
由于版本区别,在Registry V2版本中无法使用search查看私有仓库镜像,需要使用以下命令查看:
curl -XGET http://registry:5000/v2/_catalog
curl -XGET http://registry:5000/v2/{image_name}/tags/list
wjoyxt/my_web
容器互连:
# docker run -d --name redis wjoyxt/redis
# docker run -p 4567 --name webapp --link redis:db -it -v $PWD/webapp:/opt/webapp wjoyxt/my_web /bin/bash
--link标志创建了两个容器间的父子连接。这个标志需要两个参数:一个是要连接的容器的名字,另一个是连接后容器的别名。这个例子中,把新容器连接到redis容器,并使用db作为别名。别外让我们可以访问公开的信息,而无须关注底层容器的名字。连接让父容器有能力访问子容器,并且把子容器的一些连接细节分享给父容器,这些细节有助于配置应用程序并使用这个连接。
连接也能得到一些安全上的好处。注意到启动Redis 容器时,并没有使用-p标志公开Redis的端口。因为不需要这么做。通过把容器连接在一起,可以让父容器直接访问任意子容器的公开端口。更妙的是,只有使用--link标志连接到这个容器的容器才能连接到这个端口。容器的端口不需要对本地宿主机公开,现在我们已经拥有一个非常安全的模型。在这个模型里,容器化的应用程序限制了可被攻击的界面,减少了公开暴露的网络。
注意:也可以把多个容器连接在一起。但是被连接的容器必须运行在同一个Docker宿主机上。不同Docker宿主机上运行的容器无法连接。
Docker在父容器里的以下两个地方写入了连接信息:
- /etc/hosts文件里
- 包含连接信息的环境变量中
Dockerfile指令:
CMD:用于指定一个容器启动时要运行的命令,类似于RUN指令,只是RUN指令是指定镜像被构建时要运行的命令。可以在docker run命令中覆盖CMD指令。
CMD ["/bin/bash","-l"]
ENTRYRPOINT:与CMD非常类似,区别是ENTRYPOINT指令提供的命令不容易在启动容器时被覆盖,如果需要可以在运行时使用docker run的--entrypoint标志来覆盖
WORKDIR:用来在从镜像创建一个新容器时,在容器内部设置一个工作目录,ENTRYPOINT 和/或 CMD指定的程序会在这个目录下执行
ENV:用来在镜像构建过程中设置环境变量,也可以使用docker run命令行的 -e 标志来传递环境变量,这些变量将只会在运行时有效。
ENV MY_PATH /opt/app
WORKDIR $MY_PATH
#docker run -it -e "MY_PATH=/opt/app" wjoyxt
USER:用来指定该镜像会以什么样的用户去运行,可以指定用户名或UID以及组或GID,甚至是两者的组合。不过可以用docker run -u 选项来覆盖该指令指定的值
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group
VOLUME:用来向基于镜像创建的容器添加卷。一个卷是可以存在于一个或者多个容器内的特定的目录,这个目录可以绕过联合文件系统,并提供如下共享数据或者对数据进行持久化的功能。
- 卷可以在容器间共享和重用
- 一个容器可以不是必须和其他容器共享卷
- 对卷的修改是立时生效的
- 对卷的修改不会更新镜像产生影响
- 卷会一直存在直到没有任何容器再使用它
卷功能让我们可以将数据(如源代码)、数据库或者其他内容添加到镜像中而不是将这些内容提交到镜像中,并且允许我们在多个容器间共享这些内容。
VOLUME ["/opt/project"] 这条指令将会为基于此镜像创建的任何容器自动创建一个名为/opt/project的挂载点
VOLUME ["/opt/project", "/data"] 也可以通过指定数组的方式指定多个卷
ADD:用来将构建环境下的文件和目录复制到镜像中,Docker通过目的地址参数末尾的字符来判断文件源是目录还是文件。如果源目标地址以 / 结尾,那么Docker就认为源位置指向的是一个目录。文件源也可以使用URL的格式。
值得一提的是,ADD在处理本地归档文件(tar archive)时,如果将一个归档文件(合法的归档文件包括 gzip、bzip2、xz)指定为源文件,Docker会自动将归档文件解开(unpack)
ADD latest.tar.gz /var/www/wordpress/
Docker解开归档文件的行为和使用带-x选项的tar命令一样:该指令执行后的输出是原目的目录已经存在的内容加上归档文件中的内容。如果目的位置的目录下已经存在了和归档文件同名的文件或者目录,那么目的位置中的文件或者目录不会被覆盖。
如果目的位置不存在的话,Docker将会为我们创建这个全路程,包括路径中的任何目录。新创建的文件和目录的模式为0755,并且UID和GID都是0
注意:ADD指令会使得构建缓存变得无效,这一点非常重要。如果通过ADD指令向镜像添加一个文件或目录,那么这将使Dockerfile中的后续指令都不能继续使用之前的构建缓存
COPY:其非常类似于ADD,它们根本的不同是COPY只关心在构建上下文中复制本地文件,而不会去做文件提取(extraction)和解压(decompression)的工作。
COPY conf.d/ /etc/apache2/
ONBUILD:为镜像添加触发器(trigger)。当一个镜像被用做其他镜像的基础镜像时(比如你的镜像需要从某未准备好的位置添加源代码,或者你需要执行特定于构建镜像的环境的构建脚本),该镜像中的触发器将会被执行。
触发器会在构建过程中插入新指令,我们可以认为这些指令是紧跟在FROM之后指定的。触发器可以是任何构建指令。例如:
ONBUILD ADD . /app/src
ONBUILD RUN cd /app/src && make
上面的代码将会在创建的镜像中加入ONBUILD触发器,ONBUILD指令可以在镜像上运行docker inspect命令来查看。
ONBUILD触发器会按照在父镜像中指定的顺序执行,并且只能被继承一次(也就是说只能在子镜像中执行,而不会在孙子镜像中执行)。如果我们再基于wjoyxt/my-web 构建一个镜像,则新镜像是wjoyxt的孙子镜像,因此在该镜像的构建过程中,ONBUILD触发器是不会被执行的。
注意:这里有好几条指令是不能用在ONBUILD指令中的,包括FROM、MAINTAINER和ONBUILD本身。之所以这么规定是为了防止在Dockerfile构建过程中产生递归调用的问题。
在Nginx配置文件里面设置成daemon off;选项阻止Nginx进入后台,强制其在前台运行。这是因为要想保持Docker容器的活跃状态,需要其中运行的进程不能中断。默认情况下,Nginx会以守护进程的方式启动,这会导致容器只是短暂运行,在守护进程被fork启动后,发起守护进程的原始进程就会退出,这时容器就停止运行了。
FAQ:
# docker exec -t -i b69d5e9ac58b /bin/bash
Error response from daemon: Unsupported: Exec is not supported by the lxc driver
解决方法:vim /etc/sysconfig/docker 删除 --exec-driver=lxc 然后重启docker即可 (官方已经早就不推荐使用lxc了)