q4561231 发表于 2018-1-6 16:23:19

Poer李

Docker入门笔记(3) – image和container
  docker最简单的运行关系是这样的
http://www.fangyunlin.com/wp-content/uploads/2015/07/docker%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.gif

镜像仓库和镜像/registry and image
  registry是docker镜像的仓库。默认仓库是https://registry.hub.docker.com/。
  镜像(image)是存放在registry里的。
  我们可以直接在这里获取到centos、ubuntu等操作系统的镜像。这种系统镜像一般用来做二次定制,定制私有业务。
  此外还有一些具体定制的镜像,比如tomcat、apache、nginx、mysql、mongodb、redis等。这些镜像的操作系统都裁剪的很小,所以一些简单需求直接拿这些镜像来用,会方便一些。centos、ubuntu这些系统基础镜像大小都在200M以上,而像busybox、flannel这些具体定制的镜像都不到50M。

以镜像为基础运行一个容器/run a container from image
  我先拉取一个busybox镜像下来。
  

root@docker:~# docker pull busybox  
latest: Pulling from busybox
  
511136ea3c5a: Pulling fs layer
  
511136ea3c5a: Download complete
  
df7546f9f060: Download complete
  
ea13149945cb: Download complete
  
4986bf8c1536: Download complete
  
Status: Downloaded newer image for busybox:latest
  
root@docker:~# docker images

  
REPOSITORY          TAG               IMAGE>  
busybox             latest            4986bf8c1536      7 weeks ago         2.433 MB
  
busybox             buildroot-2014.02   4986bf8c1536      7 weeks ago         2.433 MB
  
root@docker:~#
  

  

  可以看到busybox这种定制版本的镜像就很小,才3M不到。以这个镜像为基础运行一个contaienr:
  

root@docker:~# docker run -it busybox  
/ # whoami
  
root
  
/ # date
  
Sat Feb 21 06:07:57 UTC 2015
  
/ # uname -r
  
3.13.0-32-generic
  
/ #
  

  

  我们可以登陆 https://registry.hub.docker.com/ 很直观的查询有哪些可用的镜像以及使用方法。
  我比较常用的镜像有


[*]centos:centos6
[*]tomcat:7
[*]mongo:2
container 状态
  启动另外一个终端,查看container状态:
  

root@docker:~# docker ps
  
CONTAINER>  
861856052a59      busybox:buildroot-2014.02   "/bin/sh"         10 seconds ago      Up 10 seconds                           evil_newton
  

  

  这时候输入exit或者直接ctrl+D可以退出这个container。这之后container会变成exited状态,并不会停留在后台执行。也就是说,container默认不会自动销毁。
  

# root@docker:~# docker ps
  
CONTAINER>  
root@docker:~# docker ps -a

  
CONTAINER>  
861856052a59      busybox:buildroot-2014.02   "/bin/sh"         3 minutes ago       Exited (0) 4 seconds ago                     evil_newton
  
root@docker:~#
  

  


[*]image只是一个文件,运行起来之后的东西叫做container
[*]一个image可以启动多个contaienr
[*]每个container之间的读写变更不会相互影响
[*]container的读写变更不会影响到image
[*]默认请款下,contaienr退出后会保存在磁盘上,不会自动销毁
[*]docker ps只能查看up状态的contaienr,要查看所有状态的container需要加 -a 参数
  上面docker run命令,加了-i -t 两个参数。-i保证交互式输入。-t表示分配tty终端。这两个都和交互式输入输出有关系,默认加上即可,和本主题无关,我不想深究。大家在后期可以试试不加这两个参数的效果,对比一下。现在对比,除了无法输入输出,其他应该体验不出来。这个话题以后也许会再讨论。

前台和后台
  上面通过 -i -t 的方式把 container 挂到终端上运行。这个只是在学习和打包 image 的时候会用到。如果是在线上业务中,把 contaienr 直接作为后台程序运行会更合适点。使用参数 -d 就行了。
  

root@docker:~# docker run -it -d busybox  
0976249c0af6baab618043187ce067faba27832e8cf85a7d434ba6b2c25256aa
  
root@docker:~# docker ps

  
CONTAINER>  
0976249c0af6      busybox:buildroot-2014.02   "/bin/sh"         3 seconds ago       Up 2 seconds                            angry_archimedes
  
root@docker:~#
  

  


  -d 后 busybox 不会在前台运行,docker直接给出 container>
网络服务相关的 container
  基本所有业务都是需要通过网络对外提供服务的。所以我们可以通过 docker run -p 参数来实现。
  docker run -p 80,在主机上找一个随机端口和 container 的 80 端口做映射(个人觉得比较没用)
  docker run -P,在主机上找对应的若干个随机端口,和 image 文件指定的 expose 端口做映射(个人觉得比较没用)
  docker run -p 10080:80,把主机的 10080 端口和 contaienr的 80 端口做映射。这时候业务要通过主机IP访问 container 里的 80 端口业务,要访问的可是 10080 端口。
  docker run -p 192.168.0.10:10080:80,把主机的 192.168.0.10 IP的 10080 端口和 container 里的 80 端口做映射。
  docker run -p -p -p,如果有多个端口需要映射,可以写多次 -p 参数。
  

root@docker:~# docker run -p 80:80 -p 23:23 -d -it busybox  
13af89b8ef87c857cd1efb88f8fd5b8ffeca3faea691bcaa73c224fcc126183d
  
root@docker:~# docker ps

  
CONTAINER>  
13af89b8ef87      busybox:buildroot-2014.02   "/bin/sh"         4 seconds ago       Up 4 seconds      0.0.0.0:23->23/tcp, 0.0.0.0:80->80/tcp   fervent_bohr
  
root@docker:~# netstat -ntpl
  
Active Internet connections (only servers)
  
Proto Recv-Q Send-Q Local Address         Foreign Address         State       PID/Program name
  
tcp      0      0 0.0.0.0:22            0.0.0.0:*               LISTEN      916/sshd
  
tcp6       0      0 :::23                   :::*                  LISTEN      1780/docker-proxy
  
tcp6       0      0 :::80                   :::*                  LISTEN      1789/docker-proxy
  
tcp6       0      0 :::22                   :::*                  LISTEN      916/sshd
  

  

  大家观察下上面输出。

为什么我的 container 总是退出?
  docker run 一个 container 的时候,最后都需要加一个 CMD 参数,表示我 container 要启动什么程序。一旦这个程序退出或者挂到后台,就会导致整个 container 退出结束。从经验上看,下面涵盖了大多数情况:


[*]程序无法启动

[*]没有指定正确的程序路径或者程序不存在
[*]启动程序的参数正确,比如没有这个参数
[*]程序配置文件有错误

[*]程序默认挂到后台执行了
  比如我们执行 docker run -it -d busybox,其实 busybox 有一个默认的 CMD 值,是 /bin/sh ,也就是等同于 docker run -it -d busybox /bin/sh 。这两句命令是一样的。 /bin/sh 这个程序会一直等待键盘输入,所以不会退出。

定制自己需要的镜像

基于 container 进行 commit
  光有基础系统的 image 只能玩一玩,没什么实际意义。我们尝试定制一个有自己功能的 image。
  创建一个 container ,并且进入 container 中进行操作:
  

docker run -it busybox /bin/sh  

  

  在 container 中创建文件 /usr/bin/run.sh
  

root@docker:~# docker run -it busybox /bin/sh  
/ # pwd
  
/
  
/ # vi /usr/bin/run.sh
  

  

  内容如下:
  

#!/bin/sh  

  
COUNT=0
  
while(true); do
  
COUNT=$(($COUNT+1))
  
echo $COUNT
  
sleep 2
  
done
  

  

  授予执行权限:
  

chmod 755 /usr/bin/run.sh  

  

  测试,直接输入命令 run.sh 执行,可见终端每2秒就会输出一个计数,并且永不退出(while(true))。
  

/ # run.sh  
1
  
2
  
3
  
4
  
5
  
6
  
...
  

  


  + C退出脚本,再exit或者 + D退出 container 。这时候可以通过 docker ps -a 看到 container 处于 exitted 状态,并且获得 container>  

docker commit d3 cst05001/study  

  

  可以把该 container 提交为 docker 默认镜像仓库下,名为 cst05001/study 的镜像。不过这只是一个标记,镜像只存在于本地,并未真正的传到镜像服务器,只能本地使用。
  

root@docker:~# docker images
  
REPOSITORY          TAG               IMAGE>  
cst05001/study      latest            a836bfbda876      2 minutes ago       2.433 MB
  
busybox             buildroot-2014.02   4986bf8c1536      7 weeks ago         2.433 MB
  
busybox             latest            4986bf8c1536      7 weeks ago         2.433 MB
  

  

  我们尝试运行我们定制的这个镜像:
  

root@docker:~# docker run -it cst05001/study run.sh  
1
  
2
  
3
  
...
  

  

  成功。

Dockerfile(推荐)
  通过 Dockerfile 进行镜像定制是在生产环境更高效更稳定的方法。不过我会放到以后再表。

push image
  之前有说,我们定制的镜像并未传送到镜像服务器。如果希望共享出这个镜像给多台服务器使用,则需要把镜像推送到镜像服务器上(registry)。步骤大致如下:


[*]在镜像服务器上注册自己的账号,创建自己的仓库(如果是自己创建的registry可以略过这一步)
[*]docker login,输入账号、密码、邮箱三个信息进行登陆验证
[*]docker push <镜像名(tag)全程>
  比如我们提交刚才的 cst05001/study,则可以这么做
  

root@docker:~# docker login  
Username: cst05001
  
Password:
  
Email: 65141838@qq.com
  
Login Succeeded
  
root@docker:~# docker push cst05001/study
  
The push refers to a repository (len: 1)
  
Sending image list
  
Pushing repository cst05001/study (1 tags)
  
511136ea3c5a: Image already pushed, skipping
  
df7546f9f060: Image already pushed, skipping
  
ea13149945cb: Image already pushed, skipping
  
4986bf8c1536: Image already pushed, skipping
  
a836bfbda876: Image successfully pushed
  
Pushing tag for rev on {https://cdn-registry-1.docker.io/v1/repositories/cst05001/study/tags/latest}
  

  

  现在我们就可以在全球所有接入互联网的机器上直接通过命令
  

docker pull cst05001/study  

  

  获取这个镜像,或者直接用命令
  

docker run cst05001/study run.sh  

  

  获取并运行这个镜像了。

第三方 registry
  由于一些不方便讲的原因,在大陆地区使用官方 registry 经常会有下面几个问题


[*]pull速度慢
[*]pull失败
[*]push速度慢
[*]push失败
[*]各种奇怪问题
  所以就催生了第三方的 registry。我比较信赖的国内 registry 有docker.cn,最近刚发现改名成 https://containerops.cn/ 了。这个 registry 曾经缓存了 docker 官方 registry 的所有内容,据说一星期更新一次。用了 又拍云 的加速服务,还可以,实测大概两三百kbytes/s。可是改版后官方镜像不见了。所以如果你懒得搭建自己的私有registry,可以直接用他的。

推送镜像到 containerops.cn
  前提是已经在 containerops.cn 注册了账号,并且创建了镜像库。登陆账号(如果你已经登陆了,可以略过这个步骤)。我偷个懒,把刚才的 cst05001/study 镜像做一个别名,也绑定到 docker。是的,image 名称也起到指定 registry地址、仓库的作用。再然后推送镜像就可以了。
  

root@docker:~# docker login containerops.cn  
Username: cst05001
  
Password:
  
Email: 65141838@qq.com
  
Login Succeeded
  
root@docker:~# docker tag cst05001/study containerops.cn/cst05001/study
  
root@docker:~# docker push containerops.cn/cst05001/study
  
The push refers to a repository (len: 1)
  
Sending image list
  
Pushing repository containerops.cn/cst05001/study (1 tags)
  
Image 511136ea3c5a already pushed, skipping
  
Image df7546f9f060 already pushed, skipping
  
Image 4986bf8c1536 already pushed, skipping
  
Image ea13149945cb already pushed, skipping
  
a836bfbda876: Image successfully pushed
  
Pushing tag for rev on {https://containerops.cn/v1/repositories/cst05001/study/tags/latest}
  
root@docker:~#
  

  

部署私有 registry
  这个是挺重要的一件事情,我会单独开一章来表。

小建议
  请执行 docker run –help ,把每一个参数都一个字一个字的读一遍。这样挺好的。

问题
  本文在使用第三方 registry 的时候,漏了一个重要的点没有说。如果有亲自测试,一定会遇到,并且不解决不行,但是会有明显的报错以及提示解决方法。请问这是什么?
页: [1]
查看完整版本: Poer李