docker目标
"Build,Ship and Run Any App,Anywhere"
,即通过对应用组件的封装,分发,部署,运行等生命周期的管理,达到应用组件级别的"一次封装,到处运行"
。这里的应用组件,既可以是一个Web应用,也可以是一套数据库服务,甚至是一个操作系统或编译器。
Linux容器技术
基础
Docker引擎的基础是Linux容器(Linux Containers,LXC)技术。
描述
容器有效的将由单个操作系统管理的资源划分到孤立的组中,以便更好的在孤立的组之间平衡有冲突的资源使用需求。与虚拟机相比,这样既不需要指令级模拟,也不需要即时编译。容器可以在核心CPU本地运行指令,而不需要任何专门的解释机制。此外,也避免了准虚拟化和系统调用替换中的复杂性。
docker优势
自身优势
- 更快速的交付和部署
- 更高效的资源利用
- 更轻松的迁移和扩展
- 更简单的更新管理
对比VM
- Docker容器很快,启动和停止可以秒级实现
- Docker容器对系统资源需求很少,一台主机上可以同时运行数千个Docker容器
- Docker通过类似Git的操作来方便用户获取,分发和更新应用镜像,指令简明,学习成本低
- Docker通过Dockerfile配置文件来支持灵活的自动化创建和部署机制,提高工作效率
docker核心
镜像
容器
创建容器
可以使用docker create
命令新建一个容器,使用该命令新建的日容器处于停止状态,可以使用docker start
来启动。
可以使用docker run
命令新建并且启动容器,例如:
$ sudo docker run ubuntu /bin/echo 'hello world'
对于该操作,Docker
在后台的标准操作包括:
- 检查是否存在本地image,如果不存在就从regitry(一般从公共registry Dcokerhub)下载。
- 利用image创建并启动容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中
- 从地址池配置一个IP给容器
- 执行用户指定的应该程序
- 执行完毕后容器被终止
下面的命令开启bash终端,允许用户交互:
$ sudo docker run -i -t ubuntu /bin/bash
更多的时候,需要让Docker容器在后台以守护态(Daemon)运行,通过加-d
参数:
[root@localhost ~]# docker run -d wangyp/javaweb:0.1
2b20afd1a889e808612246cc387dbf962eedaaf980be2d0cde2696e2a9cf41c6
[root@localhost ~]#
在docker run
时候如果添加--rm
标记,则容器在终止后会立刻删除,但是--rm
和-d
命令不能同时使用。
容器停止
通过docker ps
获取docker 容器,docker logs containerid
获取运行的某容器的log信息,使用docker stop
来停止容器。
-d
后台容器进入
1.使用attach
[root@localhost ~]# docker run -idt ubuntu
1e27ea6191568f747b87ba05ef65fe39251d0b0432715c5f3fc4e9c13d25893f
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1e27ea619156 ubuntu "/bin/bash" 9 seconds ago Up 5 seconds reverent_nobel
[root@localhost ~]# docker attach reverent_nobel
root@1e27ea619156:/#
但是使用attach很不方便,当多个窗口同时attach到同一容器时,所有窗口都会同步显示。
2.使用exec
[root@localhost ~]# docker run -idt ubuntu
6810155329a22b57ce7aaaef925ae039adb28a4a8e49822ffc7789cff274be1d
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6810155329a2 ubuntu "/bin/bash" 11 seconds ago Up 10 seconds silly_euler
[root@localhost ~]# docker exec -it 6810155329a2 /bin/bash
root@6810155329a2:/#
删除容器
rmi
命令,加-f
强制删除:
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6810155329a2 ubuntu "/bin/bash" 4 minutes ago Up 4 minutes silly_euler
[root@localhost ~]# docker rm -f 6810155329a2
6810155329a2
[root@localhost ~]#
容器导入导出
export
导出:
[root@localhost images]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eddd020cfc6a ubuntu "/bin/bash" About a minute ago Up About a minute sad_jones
[root@localhost images]# docker export eddd >ubuntu_run.tar
[root@localhost images]# ls
ubuntu_run.tar
[root@localhost images]#
import
导入:
[root@localhost images]# docker import ubuntu_run.tar ubuntu:0.1
sha256:edb3c05a4557ff7dce6344a7fb5f5afe3e62bfa4b91c3f9597b6522bd900e999
[root@localhost images]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 0.1 edb3c05a4557 8 minutes ago 118.3 MB
仓库
搭建image私有库
image公有库是dockerhub,但由于一系列原因,搭建私有库是那么重要。
$ sudo docker pull registry
下载完之后我们通过该镜像启动一个容器
$ sudo docker run -d -p 5000:5000 registry
默认情况下,会将仓库存放于容器内的/tmp/registry目录下,这样如果容器被删除,则存放于容器中的镜像也会丢失,所以我们一般情况下会指定本地一个目录挂载到容器内的/tmp/registry下,如下:
$ sudo docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry
可以看到我们启动了一个容器,地址为:192.168.112.136:5000。
<font color="red">
<big>挂载本地文件夹时遇到的问题</big>
挂载本地文件夹时,由于CentOS7中的安全模块selinux把权限禁掉了,所以需要加权限,有以下三种方式
- 在运行容器的时候,给容器加特权:
docker run -i -t --privileged=true -v /home/docs:/src waterchestnut/nodejs:0.12.0
- 临时关闭selinux
示例:su -c "setenforce 0"
之后执行:docker run -i -t -v /home/docs:/src waterchestnut/nodejs:0.12.0
- 添加selinux规则,将要挂载的目录添加到白名单
示例:chcon -Rt svirt_sandbox_file_t /home/docs
之后执行:docker run -i -t -v /home/docs:/src waterchestnut/nodejs:0.12.0
</font>
测试私有库
接下来我们就要操作把一个本地镜像push到私有仓库中。首先在132机器下pull一个比较小的镜像来测试(此处使用的是busybox)。
$ sudo docker pull busybox
接下来修改一下该镜像的tag。
$ sudo docker tag busybox 192.168.112.136:5000/busybox
接下来把打了tag的镜像上传到私有仓库。
$ sudo docker push 192.168.112.136:5000/busybox
可以看到push失败,具体错误如下:
2015/01/05 11:01:17 Error: Invalid registry endpoint https://192.168.112.136:5000/v1/: Get https://192.168.112.136:5000/v1/_ping: dial tcp 192.168.112.136:5000: connection refused. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry 192.168.112.136: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/192.168.112.136:5000/ca.crt
因为Docker从1.3.X之后,与docker registry交互默认使用的是https,然而此处搭建的私有仓库只提供http服务,所以当与私有仓库交互时就会报上面的错误。为了解决这个问题需要在启动docker server时增加启动参数为默认使用http访问。修改docker启动配置文件(此处是修改132机器的配置)Ubuntu下配置文件地址为:/etc/init/docker.conf,在其中增加–insecure-registry 192.168.112.136:5000如下所示:
$ sudo vi /etc/init/docker.conf
centos在/etc/sysconfig/docker文件中修改
# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--selinux-enabled --log-driver=journald --insecure-registry 192.168.17.132:5000'
DOCKER_CERT_PATH=/etc/docker
修改完之后,重启Docker服务。
$ sudo restart docker
重启完之后我们再次运行推送命令,把本地镜像推送到私有服务器上。
$ sudo docker push 192.168.112.136:5000/busybox
可以看到镜像已经push到私有仓库中去了。
接下来我们删除本地镜像,然后从私有仓库中pull下来该镜像。
$ sudo docker pull 192.168.112.136:5000/busybox
到此就搭建好了Docker私有仓库。上面搭建的仓库是不需要认证的,我们可以结合nginx和https实现认证和加密功能。
管理私有仓库
查询
如果我们想要查询私有仓库中的所有镜像,使用docker search
命令:
# docker search registry_ip:5000/
如果要查询仓库中指定账户下的镜像,则使用如下命令:
# docker search registry_ip:5000/account/
同时也可以指定镜像查询。
<font color="blue" >可以指定search库
</font>
在/etc/sysconfig/docker
中修改:
# If you want to add your own registry to be used for docker search and docker
# pull use the ADD_REGISTRY option to list a set of registries, each prepended
# with --add-registry flag. The first registry added will be the first registry
# searched.
ADD_REGISTRY='--add-registry 192.168.17.132:5000'
删除
目前尚未找到方法删除私有仓库中的镜像,尝试过直接从仓库存储目录中删除镜像文件,但是并不能成功删除镜像。
数据管理
数据卷
将本地一个目录挂载到容器内的/tmp/registry下,如下:
$ sudo docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry
数据卷容器
-v
创建数据卷:
[root@localhost images]# docker run -it -v /dbdata --name dbdata ubuntu
root@90de3afd15e0:/# ls
bin core dev home lib64 mnt proc run srv tmp var
boot dbdata etc lib media opt root sbin sys usr
root@90de3afd15e0:/# cd dbdata/
--volumes-from
使用数据卷
[root@localhost ~]# docker run -it --volumes-from dbdata --name db1 ubuntu
root@7044aeda3542:/# ls
bin core dev home lib64 mnt proc run srv tmp var
boot dbdata etc lib media opt root sbin sys usr
root@7044aeda3542:/# cd /dbdata/
root@7044aeda3542:/dbdata# touch 123
如果删除了关在的容器,数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着他的容器时显式使用docker rm -v
命令来指定同时删除关联的容器。
网络配置
映射端口
1.-p
映射本地端口到容器端口
$ sudo docker run -d -p 5000:5000 registry
容器互联
--link
实现容器互联
[root@localhost ~]# docker run -d --name db1 ubuntu
[root@localhost ~]# docker run -it --rm --link db1:db --name db3 ubuntu /bin/bash
容器具体互联信息:
[root@localhost ~]# docker run -it --rm --link db1:db --name db3 ubuntu /bin/bash
root@56c9d340222d:/# env
HOSTNAME=56c9d340222d
DB_NAME=/db3/db
TERM=xterm
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
SHLVL=1
HOME=/root
_=/usr/bin/env
root@56c9d340222d:/# cd /etc/hosts
bash: cd: /etc/hosts: Not a directory
root@56c9d340222d:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.4 db 7044aeda3542 db1
172.17.0.5 56c9d340222d
root@56c9d340222d:/#