docker镜像:业务代码和运行环境进行整体的打包.
1.1快速创建环境(开发,测试,生产)
1.2整体交付(运行环境+代码(之前只是代码))
1.3可保证环境(开发,测试,生产)的一致性
1.4更好的完成devops
镜像(Image)就是一堆只读层(read-only layer)的统一视角
这些层是Docker内部的实现细节,并且能够在主机的文件系统上访问到,统一文件系统(union file system)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统,你可以在你的主机文件系统上找到有关这些层的文件.它们存在于/var/lib/docker/aufs目录下
1
| sudo tree -L 1 /var/lib/docker/
|
容器=镜像+读写层.并且容器的定义并没有提及是否要运行容器
1 2 3 4 5 6
| docker create <image_id> docker start <image_id> docker run <image_id>
|
所以容器(container)的定义和镜像(image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的.
镜像分层技术:AUFS (Another UnionFS)支持将多个目录挂载到同一个虚拟目录下.已构建的镜像会设置成只读模式,read-write操作是在read-only上的一种增量操作.
把一个镜像创造成一个容器才能往里写东西.
所谓UnionFS就是把不同物理位置的目录合并mount到同一个目录中.UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 mount在一起
然后,你就可以对这个只读的CD/DVD上的文件进行修改(当然,修改的文件存于硬盘上的目录里)
docker容器管理技术,是内核技术,容器本身是进程 其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西
它并不是虚拟技术(VM),docker最关键的点是提出了docker images标准化,image打包了应用:如nginx镜像,通过镜像启动一个nginx容器,其实就是在主机上启动了一个nignx进程.
容器不等于微服务,推荐只运行一个服务,如果运行多个服务,需要结合进程管理工具(supervisor,S6),
因为容器本身就是进程,所以数据库容器也可以运行,但需要对数据做好保护(volume).
既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数.CMD 指令就是用于指定默认的容器主进程的启动命令的,
在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如,ubuntu 镜像默认的 CMD 是 /bin/bash,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash.
容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念.
ubuntu install docker
1 2 3 4 5 6 7 8 9 10 11 12
| sudo apt-get update curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] \ https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt-get update sudo apt-cache policy docker-ce sudo apt-get install -y docker-ce sudo systemctl status docker sudo usermod -aG docker $(whoami) service docker start docker images
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| sudo apt-get update sudo apt-get install docker.io apt-get purge docker.io* apt-get dist-upgrade -y apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys \ 58118E89F3A912897C070ADBF76221572C52609D echo "deb https://apt.dockerproject.org/repo debian-jessie main" | \ tee /etc/apt/sources.list.d/docker.list apt-get update apt-get install docker-engine -y apt-get purge docker-engine -y apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 \ --recv-keys 58118E89F3A912897C070ADBF76221572C52609D echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main " > \ /etc/apt/sources.list.d/docker.list apt-get update apt-get install docker-engine=1.10.1-0~trusty apt install docker.io docker -v
|
启动docker服务
docker官方镜像 类似AppStore 是由各自官方机构做的镜像认证后,上传到docker官方镜像的,这个仓库的地址是在国外,所以下载的速度会慢点
利用镜像的分层技术,如果主机上已有layer(层)存在,那只会下载新增加的layer(类似git代码提交机制)
1 2 3 4 5 6 7 8 9
| service docker start docker port nostalgic_morse 5000 vim /usr/lib/systemd/system/docker.service ExecStart=之前的不要动加上 --insecure-registry=0.0.0.0/0 systemctl daemon-reload systemctl restart docker ps aux |grep docker
|
容器操作命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| docker run -dit -p 80:80 --name app nginx docker create -p 80:80 --name app nginx docker start app docker commit <container-id> docker build -t app . docker exec -it app bash docker exec -it app bash ls /tmp docker rename app new_app docker stop/kill/pause/unpause/restart <container_id> docker inspect/stats/port/ps/top/dip/dpid <container-id> docker top app docker ps docker ps -a docker inspect nginx/app |grep -i memory docker stats $(docker ps | awk 'NR>1 {print $NF}') docker update -m 256m app docker rm -f -v app docker copy 本地文件 容器路径 docker copy app:/usr/share/ngxin/html/index.html . docker copy index.html app:/tmp docker export app (把容器保存成tar文件) docker import app.tar (把tar文件导会到镜像列表)
|
镜像命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| docker commit -a admin@femnyy.com -m 'app commit image' app app:2.0 docker save nginx >nginx.tar docker rmi nginx docker load < nginx.tar docker images docker history <image_id> docker pull nginx docker tag nginx 192.168.1.116:5000/nginx:last docker push 192.168.1.116:5000/nginx:last docker search nginx
|
容器生成镜像
# 进入容器
docker exec -it docker_web_1 bash
# 在容器中进行操作
pip install gevent==1.3.3
# 退出容器
exit
docker ps |grep docker_web
# 得到 conta id: fdeb8e0c67ee
docker images |grep docker_web
# 得到repository:docker_web:latest
docker history docker_web:latest |wc -l
docker commit -m "pip install gevent==1.3.3" fdeb8e0c67ee docker_web:latest
docker history docker_web:latest |wc -l
容器与镜像
镜像不能直接访问,只有启动成容器,才可以访问.镜像和容器的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体.容器可以被创建、启动、停止、删除、暂停等.同一个 Images 可生成多个不同配置的 Container.
容器连接(相当于进程间的通信吧)
1 2 3 4 5 6
| sudo docker run -d --name db training/postgres sudo docker run -d -P --name web --link db:db training/webapp python app.py docker ps
|
Volume(持久化容器数据,以及容器之间共享数据)
保留容器的数据
当容器删除时,就是杀死进程,只要我们的数据在,当再启动时,数据又回来了,但我们想在容器中产生的数据保留起来
容器间的数据共享(root用户下,主机巻)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| docker run -d -v /web_data:/tmp:ro --name data-container nginx cd /web_data mkdir files touch test.file docker exec -it data-container ls /tmp docker run -d --volumes-from data-container --name web-container nginx docker run -d --volumes-from data-container --name web-container-2 nginx docker exec -it web-container ls /tmp docker exec -it web-container bash cd /tmp touch a.txt exit cd /web_data touch a.txt
|
Volume分为容器卷(在Dockerfile写了VOLUME)和主机卷
容器卷的定义的目录,将会自动保存在宿主机的/var/lib/docker/volumes目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| mkdir docker cd docker && vim Dockerfile FROM centos:7 RUN yum -y install epel-release && \ yum -y install nginx && \ yum clean all EXPOSE 80 443 VOLUME ["/usr/share/nginx/html"] CMD ["nginx","-g", "daemon off;"] docker build -t app . cd /var/lib/docker/volumes docker rm -f web-container data-container docker run -d --name app app ll docker rm -f -v app
|
主机卷(/web-data),这个不仅仅会在/var/lib/docker/volumes:/usr/share/nginx/html保留,双保险.
1
| docker run -d -p 80:80 --name app -v /web-data:/tmp app
|
备份app容器中 /dbdata容器巻中的数据–>打包在容器中的/backup/backup.tar–>将此包copy到主机的当前目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| docker run --rm --volume-from app -v ${pwd}:/backup ubuntu \ tar cvfz /backup/backup.tar /dbdata docker run --rm --volume-from app -v ${pwd}:/backup busybox \ bash -c "cd /dbdata && tar zxvf /backup/backup.tar --strip 1" sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar sudo docker run --volumes-from dbdata2 busybox /bin/ls /dbdata
|
Docker的网络模式:nat,host,container,none,overlay
默认启动的是nat
nat需要进行端口的管理,通过docker容器转发的功能,转发到宿主机的网卡上,每次启动容器的时候,它的IP会变:
1 2 3 4 5 6 7 8 9 10 11
| docker run -d -p 80:80 --name app nginx ps -aux |grep docker /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 \ -container-ip 172.17.0.3 -container-port 80 docker restart app /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 \ -container-ip 172.17.0.3 -container-port 80 docker stop app docker start app
|
host:容器中的网卡直接与宿主机的网卡沟通:只能使用80端口,但可以固定容器的IP.攻击了容器也就相当于攻击了宿主机.
1 2 3 4
| docker run -d --name app2 --net=host nginx docker ps -a docker start -a app2
|
container模式,用于容器之间经常通信的情况:
1 2 3 4 5 6 7 8
| docker pull busybox docker run -it --name busybox1 busybox sh ip addr ctrl+p+q docker run -it --name busybox2 --net=container:busybox1 busybox sh ip addr ping busybox1
|
none模式:没有IP
1
| docker run -it --name none --net=none busybox sh
|
overlay模式,实现跨主机的通信,docker:1.10+,才有的模式.
约定的容器启动时 会被当作一个服务被consul发现,从而分发IP
1 2 3 4 5 6 7 8 9 10 11
| vim /lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 \ -H unix:///var/run/docker.sock --cluster-store=consul://192.168.1.116:8500 \ --cluster-advertise=enp2s0:2376 --insecure-registry=0.0.0.0/0 systemctl daemon-reload systemctl restart docker ps -aux |grep docket
|
在consul的主机执行就可以:hostA
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| docker pull progrium/consul docker run -d -p 8400:8400 -p 8500:8500 -p 8600:53/udp -h consul progrium/consul \ -server -bootstrap -ui-dir /ui docker ps -a 192.168.1.116:8500 docker network ls docker network create -d overlay --subnet=10.0.9.0/24 edu-net
|
当约定好的主机启动容器时,consul服务就会从地址池中取得IP,给容器使用
1 2 3 4 5 6 7 8 9 10 11
| docker run -d --name app1 --net=edu-net nginx docker exec -it app1 bash ip addr ping www.baidu.com docker run -d --name app2 --net=edu-net nginx docker exec -it app2 bash ping app1
|
官方文档
一个中文的docker文档
对docker的解释