1.docker简介以及理念
百度简介:
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
官方简介:
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。
docker起源:
Docker是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源。
Docker是通过内核虚拟化技术【namespaces(进入命名空间,工具是nsenter在util-linux安装包里面)以及cgroups等,kvm也是通过内核虚拟化的】来提供容器的资源隔离与安全保障。由于docker通过操作系统层的虚拟化实现隔离,所以docker容器在运行时不需要类似虚拟机(vm)额外的操作系统开销,docker是运行在操作系统里面的,提高资源利用率。
docker三大理念:
构建,运输和运行,也是代码发布的面临的三个问题(可以将运行程序和环境一起打包成容器)
saltstack可以做到机器版本相同,可以进行版本回滚,但是做不到环境回滚,docker可以保证不同版本的环境一致性
docker到底能做什么???
1.简化配置,可以将运行环境和代码同时放到docker里面,也降低了代码和运行环境的依赖性
2.代码流水线管理,将开发,测试,生产聚合成流水线一样的使用方式,一次构建,多次使用,保证一致性
3.提高开发效率
4.隔离应用,降低成本,提高资源利用率,没什么说的,没有虚拟机隔离得好
5.快速部署
总结:docker从不同方面的到底改变了什么?
2.docker组成部分
一个完整的Docker有以下几个部分组成: 1.dockerClient客户端 2.Docker Daemon守护进程 3.Docker Image镜像 4.DockerContainer容器 5.DockerRepository仓库
镜像:可以理解为和虚拟机的镜像类似,但是作用完全一样,就好比启动一个kvm虚拟机就必须得有一个镜像
容器:docker使用容器来运行,从镜像创建了一个实例,容器与镜像的关系类似于面向对象编程中的对象与类。容器:对象,镜像:类,docker可以对容器进行启动,停止,删除等操作,容器之间是相互隔离的,不是虚拟的,但是不会像虚拟机那样隔离的很彻底。
仓库:存储镜像的地方,相当于yum仓库的作用,就像git有仓库github一样,docker也有镜像的仓库叫dockerhub,都是使用相同的命令
注意:docker的服务端挂掉之后,所有运行在docker上的容器都会挂掉
3.docker与虚拟机和openstack之间对比
docker和虚拟机
Hypervisor是虚拟机的管理软件
docker个虚拟机之间相差了一个虚拟机管理软件,和操作系统,可以看到docker直接运行在docker引擎上面的,而虚拟机是运行在操作系统上面的。但是虚拟机之间能进行完全隔离,但docker无法像虚拟机一样提供完全的资源隔离,甚至有的地方就不隔离,比如用户空间。
重点:容器是给进程做隔离用的,虚拟机是给操作系统做隔离用的
docker和openstack
注意:
1.管理简单,意味着能操作的东西就简单,比较少,还有一个就是在复杂的情况下也就不明显,比如100个容器,管理就不简单了
2.docker容器只能启动单进程,并且必须启动在前台,如果前台进程挂掉了,容器就终止了。不建议使用ssh(docker官方不建议通过ssh连接到容器,不要将容器当做虚拟机来使用)。
4.docker安装(centos7)
4.1 Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker 。
[root@node2 ~]# uname -r
3.10.0-957.1.3.el7.x86_64
4.2 使用root
权限登录 Centos。确保 yum 包更新到最新
sudo yum update
4.3 安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
4.4 设置yum源
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
4.5 可以查看所有仓库中所有docker版本,并选择特定版本安装
yum list docker-ce --showduplicates | sort -r
4.6 安装docker
sudo yum install docker-ce #由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0
sudo yum install <FQPN> # 例如:sudo yum install docker-ce-17.12.0.ce
4.7 加入开机启动
$ sudo systemctl start docker
$ sudo systemctl enable docker
4.8 验证是否安装成功
docker version
5.docker入门
docker的三大组件:镜像(Image),仓库(Repository),容器(Container)一定要记住.
docker基础
启动docker:systemctl start docker
会帮我们生成一个docker0的网桥,ip地址为172.17.0.1
常用命令:
搜索镜像:docker search centos 会去dockerhub上搜索有关centos镜像
获取镜像:docker pull centos 会去dockerhub上下载有关centos镜像
查看镜像:docker images
导出镜像:docker save -o centos.tar centos(这个是在docker images里面可以看到的镜像名字)
删除镜像:docker rmi id号 删除镜像,在镜像里面有容器的话,删除不了
启动容器:docker run centos(镜像名称) /bin/echo ‘hello world’,如果有参数,要写在镜像名称前面,最后面跟上要执行的命令,要注意:docker必须在前台启动,当进程结束之后docker就退出了,所以上面命令执行完之后,docker的状态就退出了
查看docker状态: docker ps -a(所有运行和不运行的都显示),启动容器的时候可以通过--name指定容器名称,如不指定,docker会自动生成一个随机名称
启动一个带名称的docker容器
启动一个带名称的docker容器:docker run --name mytestdocker -t -i centos /bin/bash 新建一个mytestdocker的容器,镜像是centos,并且分配一个伪终端和打开标准输入,并且执行命令,注意:如果centos的镜像没有的话,docker会在dockerhub上pull下来,在启动
-t:让docker分配一个伪终端
-i:让docker容器的标准输入打开
可以看到我们已经进入了容器内部,但是要注意:这不是虚拟机,而是docker的容器。通过查看docker的状态可以看到,容器id一样,另外一点是id为1ac70a1ee153容器的pid为1的是/bin/bash,而centos7中pid为1的是systemd,退出输入exit
容器是给进程做隔离的,虚拟机是给操作系统做隔离的,容器不能完全隔离,但是虚拟机可以操作系统完全隔离
在容器上执行free -m
在启动容器的虚拟机里面执行free -m,可以看到容器并不完全隔离
停止容器 exit
重新启动被关闭的容器 docker start mytestdocker/容器id
但是我们发现,这回进不去容器内部了,是node2不是容器id了,该怎么进去哪?
不能进去了,因为这是docker的理念,可以在创建一个容器,但不能修改这个容器了。不可变基础设施的概念非常适合docker理念
但是可以使用命令来进入docker attach mydockertest
停止容器:docker stop 容器id/容器名称
删除容器:docker rm -f(删除正在运行的容器) 容器id/容器名称
执行完命令之后删除容器:docker run --rm centos /bin/echo "hehe"
docker进入方式
背景:
在开启docker之后,根据docker的理念【不可变的基础设施】,在容器执行exit之后,docker就关闭掉了,之后就不能进入docker内部。但是可以通过重新启动docker容器,来进行重新管理容器,但是这与docker的理念不相符
并且在生产环境中,如果输入了一个exit就将正在使用的docker容器关掉的话,也比较危险,所以,推荐另一种进入docker的方式。
1.nsenter
在前面知道docker是通过内核级虚拟化提供容器资源隔离和安全保障,我们也可以通过namespaces的工具nsenter来进入docker容器
yum install -y util-linux nsenter工具在util-linux包里面
[root@node2 ~]# nsenter --help
Usage:
nsenter [options] <program> [<argument>...]
Run a program with namespaces of other processes.
Options:
-t, --target <pid> target process to get namespaces from
-m, --mount[=<file>] enter mount namespace
-u, --uts[=<file>] enter UTS namespace (hostname etc)
-i, --ipc[=<file>] enter System V IPC namespace
-n, --net[=<file>] enter network namespace
-p, --pid[=<file>] enter pid namespace
-U, --user[=<file>] enter user namespace
-S, --setuid <uid> set uid in entered namespace
-G, --setgid <gid> set gid in entered namespace
--preserve-credentials do not touch uids or gids
-r, --root[=<dir>] set the root directory
-w, --wd[=<dir>] set the working directory
-F, --no-fork do not fork before exec'ing <program>
-Z, --follow-context set SELinux context according to --target PID
-h, --help display this help and exit
-V, --version output version information and exit
For more details see nsenter(1).
# docker inspect -f {{.State.Pid}} 容器名或者容器id //每一个容器都有.State.Pid,所以这个命令除了容器的id需要我们根据docker ps -a去查找,其他的全部为固定的格式
# nsenter --target 上面查到的进程id --mount --uts --ipc --net --pid // 输入该命令便进入到容器中
--
mount
参数是进去到
mount
namespace中
--uts参数是进入到uts namespace中
--ipc参数是进入到System V IPC namaspace中
--net参数是进入到network namespace中
--pid参数是进入到pid namespace中
--user参数是进入到user namespace中。目前docker还不支持
我们可以看到有两个bash,第一个/bin/bash是容器执行的第一个进程,-bash是我们nsenter创建的bash,所以退出容器,容器不会停止,因为/bin/bash还在继续跑着,输入exit,查看docker状态,可以看到容器还在运行,没有停止
使用脚本来管理docker的容器
#!/bin/bash
# 2018年12月25日19:40:04
# Use nsenter to access docker
docker_in(){
docker_name=$1
pid=$(docker inspect -f "{{ .State.Pid }}" $docker_name)
nsenter -t $pid -m -u -i -n -p
}
docker_in $1
执行结果
2.docker exec
不进入容器执行命令:docker exec mydockertest whoami
通过exec进入容器: docker exec -it mydockertest /bin/bash
3.docker attach
6.docker网络访问
docker run 参数 -d 启动一个容器在后台运行并且打印容器id
”nginx -g daemon off“:守护进程挂掉了,以为nginx不能运行在docker的后台,因为docker只能在前台运行,所以docker自杀了
of是在后台的方式运行,但是docker默认是单线程并且必须运行在前台,如果容器运行的命令不是那些一直挂起的命令(比如运行top
,tail),就是会认为没事做,就自动退出了
docker 容器默认会把容器内部第一个进程,也就是pid=1的程序作为docker容器是否正在运行的依据,如果docker 容器pid挂了,那么docker容器便会直接退出。
docker run的时候把command最为容器内部命令,如果你使用nginx,那么nginx程序将后台运行,这个时候nginx并不是pid为1的程序,而是执行的bash,这个bash执行了nginx指令后就挂了,所以容器也就退出了,和你这个一样的道理,pm2 start 过后,bash 的pid为1,那么此时bash执行完以后会退出,
所以容器也就退出了
查看容器的访问日志:
docker logs LcsCentos
网络访问
docker的网络访问实际上是通过服务器的nat映射到docker容器里面的ip
随机映射:
docker run -d -P --name testnginx nginx :将docker容器内的80端口映射到本地的随机端口,注意随机映射是大P
查看服务器上iptables的nat映射
指定映射
docker run -d -i -t -p 192.168.10.232:80:80 --name 'NginxTest' nginx :将docker容器的80端口映射到本地的80端口,注意用小p
指定多个端口映射
docker run -d -i -t -p 81:80 -p 443:443 --name "nginxtest" nginx :注意不要使用本地映射过得端口
查看容器映射端口
docker port LcsNginx
在nginx容器中执行命令(如果没有ifconfig命令,通过apt-get install -y net-tools,需要先apt-get update)
7.docker数据管理
数据卷方式:dockerfile中不可用
第一种挂载写法:目录随机挂载
创建一个nginx的镜像挂在到/data docker run -d -i -t --name nginx-volume-test1 -v /data nginx
执行mount可以看到nginx的容器挂载了很多镜像
mount出来的/data目录在本地那个地方那?
在/var/lib/docker/volumes/da16024b9c81a80d4bcf9076c6f81cde4f23f8092865a87ca9551f87a5dbd9b3/_data目录下touch一个文件,容器里面的data目录下也会出现一个文件
第二种挂载写法:指定目录挂载
docker run -d -i -t --name "nginx-volumn-test2" -v /data/nginx-volumn-test2:/data -p8080:80 -p8443:443 nginx
还可以挂载文件
docker run --rm -i -t -v /root/.bash_history:/1.txt nginx /bin/bash
数据卷容器方式:可以让一个容器访问另一个容器的数据卷,不管容器是否运行,可以让数据在多个容器之间共享
docker run -it --name volume-test3 --volumes-from nginx-volumn-test2 centos /bin/bash
我们在上面创建的nginx-volumn-test2容器里面的data目录touch一个123
nginx-volumn-test2 的/data目录
注意:数据卷容器只要有volume的连接就不会被删除,例如上面的nginx-volumn-test2,如果有其他容器在使用其数据卷,nginx-volumn-test2就不能被删除
8.docker镜像构建
获取所有docker容器的id
docker ps -a -q
kill所有正在运行的容器
docker kill $(docker ps -a -q )
删除所有容器
docker rm $(docker ps -a -q)
手动构建镜像
1.基于centos镜像创建一个名为nginx-20181228的的容器
docker run --name nginx-20181228 -it centos
2.安装epel源用来安装nginx
[root@a1a6fb8030c1 /]# rpm -ivh https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
3.安装nginx和vim
[root@a1a6fb8030c1 /]# yum install -y nginx && yum install -y vim
4.修改nginx的配置文件,禁止后台启动,因为docker是前台启动
[root@a1a6fb8030c1 /]# vim /etc/nginx/nginx.conf 在开头填加一行 daemon off;
5.退出容器,提交容器到镜像
[root@node2 ~]# docker commit -m "My Nginx" a1a6fb8030c1 lcs/mynginx:v1 --->提交一个描述为"My Nginx",id为a1a6fb8030c1的容器到lcs仓库版本号为v1
sha256:c47531b36ad45f4d77e6673ce4f92d2233ba70691088dcf7333c35f15fbc8784
6.查看镜像,可以看到基于cengos的镜像制作的nginx的镜像是原来的2倍还多
7.使用我们创建的镜像来创建一个nginx的容器
dockerfile构建镜像
1.编写Dockerfile文件,注意Dockerfile要大写
[root@node2 nginx]# cat Dockerfile #This Dockerfile #注释 #Base image FROM centos #寻找基础镜像 #Maintainer MAINTAINER nobody xxx@gmail.com #镜像创建人 #Common RUN rpm -ivh https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm #执行命令 RUN yum install -y nginx && yum clean all RUN echo "daemon off;" >> /etc/nginx/nginx.conf ADD index.html /usr/share/nginx/html/index.html #添加index.html到/usr/share/nginx/html/index.html EXPOSE 8888 #使用端口 CMD ["nginx"] #运行nginx
2.构建docker镜像
[root@node2 nginx]#docker build -t mynginx:v2 . -->"."指的是当前路径下,必须要Dockerfile文件和index.html文件
3.使用新构建的镜像创建容器(命令的后面也可以不加nginx,因为Dockerfile里面已经指定了容器启动完成之后要输入的命令)
9.DockerFile的应用
生产supervisor Dockerfile Dockerfile2 dockerfile docker文章
企业中docker使用:
1.系统环境层 -->创建自己要使用的系统环境层(centos)的Dockerfile
1.1 创建自己要使用的系统环境(centos)层的Dockerfile
[root@node2 centos]# vim /opt/system/centos/Dockerfile
#Docker for Centos
#Base image
FROM centos
#Maintainer
MAINTAINER lcs xx@hmail.com
#EPEL
ADD epel.repo /etc/yum.repos.d/
#Base pkg
RUN yum install -y wget mysql-devel supervisor git redia tree net-tools sudo psmisc && yum clean all
1.2 使用Dockerfile来创建系统层镜像centos
[root@node2 centos]# docker build -t lcs/centos:base .
Complete!
Loaded plugins: fastestmirror, ovl
Cleaning repos: base epel extras updates
Cleaning up list of fastest mirrors
Removing intermediate container 820056af890c
---> 6e83dbdc96c5
Successfully built 6e83dbdc96c5
Successfully tagged lcs/centos:base
1.3 查看镜像
[root@node2 centos]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
lcs/centos base 6e83dbdc96c5 5 seconds ago 295MB
nginx latest 02256cfb0e4b 34 hours ago 109MB
centos latest 1e1148e4cc2c 3 weeks ago 202MB
2.
10.docker仓库
docker命令帮助
[root@node2 ~]# docker --help Usage: docker COMMAND A self-sufficient runtime for containers Options: --config string Location of client config files (default "/root/.docker") -D, --debug Enable debug mode -H, --host list Daemon socket(s) to connect to -l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info") --tls Use TLS; implied by --tlsverify --tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem") --tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem") --tlskey string Path to TLS key file (default "/root/.docker/key.pem") --tlsverify Use TLS and verify the remote -v, --version Print version information and quit Management Commands: config Manage Docker configs container Manage containers image Manage images network Manage networks node Manage Swarm nodes plugin Manage plugins secret Manage Docker secrets service Manage services stack Manage Docker stacks swarm Manage Swarm system Manage Docker trust Manage trust on Docker images (experimental) volume Manage volumes Commands: attach Attach local standard input, output, and error streams to a running container #进入一个正在运行的容器中,docker attach 容器名称/容器id build Build an image from a Dockerfile commit Create a new image from a container's changes cp Copy files/folders between a container and the local filesystem create Create a new container diff Inspect changes to files or directories on a container's filesystem exec Run a command in arunning container #通过exec执行命令 docker exec 容器id/容器名称 whoami 或者通过exec进入容器 docker exec -it 容器id/容器名称 /bin/bash events Get real time events from the server export Export a container's filesystem as a tar archive history Show the history of an image images List images import Import the contents from a tarball to create a filesystem image info Display system-wide information inspect Return low-level information on Docker objects #获取容器内第一个进程的pid,docker inspect -f "{{ .State.Pid }}" 容器名称 kill Kill one or more running containers load Load an image from a tar archive or STDIN #导入一个镜像 docker load <nginx.tar login Log in to a Docker registry logout Log out from a Docker registry logs Fetch the logs of a container pause Pause all processes within one or more containers port List port mappings or a specific mapping for the container ps List containers pull Pull an image or a repository from a registry #下载一个镜像到仓库 docker pull nginx push Push an image or a repository to a registry rename Rename a container restart Restart one or more containers #重启容器 rm Remove one or more containers #删除容器 rmi Remove one or more images #删除镜像 run Run a command in a new container #启动一个容器 docker run --name testdocker -i -t centos /bin/bash save Save one or more images to a tar archive (streamed to STDOUT by default) search Search the Docker Hub for images #在dockerhub上搜索一个镜像 start Start one or more stopped containers #启动容器 stats Display a live stream of container(s) resource usage statistics stop Stop one or more running containers #停止容器 tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE top Display the running processes of a container unpause Unpause all processes within one or more containers update Update configuration of one or more containers version Show the Docker version information #查看docker版本 wait Block until one or more containers stop, then print their exit codes
x.docker的学习途径
docker工具
compose:使用Python语言开发,将多个相关的容器配置在一起,从而可以同时创建、启动、停止和监控它们。 machine:帮助安装docker到指定位置,包括本地虚拟机、远端云主机等,同时还管理这些主机的信息,可以很方便的操作安装在不同主机上的这些docker。 kitematic:桌面版的docker客户端(图形界面),使用JavaScript基于electron开发。 toolbox:帮助安装docker环境到Windows和Mac平台,包括Docker引擎、Compose、 Machine和 Kitematic,当然docker引擎是安装在虚拟机里面的,本地只有客户端,使用哪个虚拟机依赖于平台,toolbox会帮你搞定这一切。 distribution:Registry 2.0的实现,主要是管理和分发docker镜像,Docker Hub背后的技术。 swarmkit:嵌入在docker里面的容器编排系统,可以简单的把它和docker的关系理解成IE浏览器和Windows的关系,捆绑销售。
啦啦啦