“Docker是一个开源的应用容器引擎”,这个概念解释说了等于没说。其实就是个虚拟机,如果我们用过类似VMware这样的虚拟机软件就知道了,在windows上可以跑Linux、mac,反过来也可以。但是,如果我只是想跑一个程序,却要装上整个操作系统,包括各类无用的驱动程序、系统软件等,还要占用大量的系统资源,导致跑不了几个虚拟机就卡的不行了。请问能不能只安装运行该程序的最小安装环境呢?可以的,那就用容器!容器直接运行在操作系统内核之上的用户空间,也被称为“操作系统级虚拟化”,容器技术可以让多个独立的用户空间运行在同一台宿主机上。Docker则提供一个部署容器的程序,提供轻量、方便的管理环境。
Docker镜像与容器
镜像是基于联合文件系统的一种层式的结构,由一系列指令一步步构建出来。也可以把镜像当作容器的源代码。镜像体积小 、便携,易于分享及存储。
容器则是基于镜像启动的,容器中可以运行一个或多个进程。镜像是Docker生命周期中的构建或打包阶段(每个容器都包含一个软件镜像),而容器是启动或执行阶段。Docker容器就是一个镜像格式;一系列标准的操作;一个执行环境。
- 每个容器都有自己的root文件系统
- 每个容器都运行在自己的进程环境中
- 容器间的虚拟网络接口和IP地址都是分开的
- 使用Linux内核特性之一的cgroups将CPU和内存之类的资源独立分配给每个docker容器。
- Docker推荐单个容器只运行一个和应用程序或进程。
Docker安装启动
docker安装教程有很多,也可直接参考官网说明安装,此处略过。
docker运行权限
docker用户组的成员可以直接运行Docker,因此将使用docker的用户加入docker用户组。
docker服务
操作命令(centos):
systemctl status docker(状态) systemctl stop docker(停止) systemctl start docker(启动)
运行Docker守护进程时,可使用-H指定服务进程网络地址及端口
查看docker信息
docker info
查看docker详细安装信息,文件路径等。
docker重启已经停止的容器
docker start container_name
docker start aa3f356f0f43
Docker容器相关命令
运行容器
docker run -i -t
会产生一个交互式会话
容器命名
docker --name
附着到容器上(重新打开该容器会话)
docker attach
创建守护式容器
docker -d
查看正在运行的docker容器
docker ps
查看容器日志(容器内部在干什么)
docker logs
查看容器内进程
docker top
在容器内部运行进程
docker exec
自动重启容器
若由于某种错误导致容器停止运行,则可以自动重启
docker run --restart=always
always:代表无论退出代码是多少,都会重启该容器
on-failure:则为当容器退出代码为非0值时才会自动重启(后面还可以设置成重启次数,如: --restart=on-failure:5)。
深入容器(获取更多容器配置信息)
docker inspect
docker inspect --format选定查看结果
删除容器
docker rm
删除所有容器
docker rm `docker ps -a -q`
-a列出所有容器;-q是只返回容器ID
Docker镜像
Docker文件系统是叠加而成,最底端是一个引导文件系统。Docker利用联合加载(一次加载多个文件系统,但在外面看起来只能看到一个文件系统)在root文件系统上加载更多的只读文件系统。
查看本地镜像保存路径
可查看docker根目录,在下面的image文件夹
docker info | grep Docker Root Dir
Docker hub有两类仓库:用户仓库(由Docker用户创建)和顶层仓库(Docker内部人管理),用户仓库包含用户名和仓库名两部分,顶层仓库只包含仓库名。
查看指定镜像名
docker images 镜像名
查找docker hub上镜像
docker search
拉取镜像
docker pull
构建镜像
docker commit命令(不推荐) docker build命令和Dockerfile文件(推荐)
使用Dockerfile和docker build命令可以直接创建出镜像,因此我们只需编写Dockerfile文件进行交付(通常来说,我们并不是真正“创建”新镜像,而是基于一个已有的基础镜像。docker commit提交的只是创建容器的镜像与容器的当前状态之间有差异的部分。)
推荐方法构建镜像
1.创建目录
该目录是我们的构建环境(build environment),Docker则称此环境为上下文(context)或者构建上下文。Docker会在构建镜像时将构建上下文和该上下文中的文件和目录上传到Docker守护进程。
2.创建Dockerfile文件
从上往下执行,每条指令(如FROM)都必须为大写字母,且后面要跟一个参数。
例子:
FROM ubuntu:18.04 LABEL maintainer="james@example.com" RUN apt-get update RUN apt-get install -y nginx RUN echo 'Hi, I am in your container' \ >/var/www/html/index.html EXPOSE 80
Dockerfile执行流程:
- Docker从基础镜像运行一个容器。
- 执行一条指令,对容器作出修改。
- 执行提交一个新的镜像层(类似docker commit操作)。
- docker再基于刚提交的镜像运行一个新容器
- 执行Dockerfile中的下一条指令,直到所有指令都执行完毕。
需要注意的是,Dockerfile中即使某条指令执行失败,依然可以获得一个可以使用的镜像。Dockerfile中注释:以#号开头
3.执行构建
运行以下指令构建:
docker build .
如:docker build -t="jamtur01/static_web:v1" .
最后的“.”指明在本目录找Dockerfile文件,也可以指定git地址的Dockerfile位置。
执行,所有指令被提交,然后返回一个新镜像。
.dockerignore文件设置哪些文件不会被上传到构建上下文中去,每一行都是一条文件过滤匹配模式(类似.gitignore)。
若指令构建失败,可以使用docker run基于最后一步创建的镜像创建容器,进行下面指定直接操作,然后反过来修改Dockerfile,再尝试构建即可。
可选择使用--no-cahe参数略过缓存功能构建
docker build --no-cache -t="jamtur01/static_web:v1" .
查询镜像被构建的详情
docker history 4621f6068600
4.运行容器
使用构建好的镜像运行容器
指定端口映射
sudo docker run -d -p 18080:80 --name static_web jamtur01/static_web \nginx -g "daemon off"
-p 宿主机端口:容器端口
向外公开端口
sudo docker run -d -P --name static_web jamtur01/static_web \nginx -g "daemon off"
-P用来公开在Dockerfile中EXPOSE设置的所有端口·
(该命令会将容器内的80端口对本地宿主机公开,并绑定到宿主机一个随机端口上。并将Dockerfile中EXPOSE的所有端口一并公开。)
Dockerfile命令详解
官网:https://docs.docker.com/engine/reference/builder/
CMD:
CMD是指定容器被启动时要运行的命令,和docker run命令启动容器时后面跟的命令一样,但是docker run命令可以覆盖CMD指令。(区别于RUN,RUN是指定镜像被构建时要运行的命令)。
ENTRYPOINT
和CMD类似,但是docker run命令行中指定的任何参数都会再次传给ENTRYPOINT指令中指定的命令。(命令行中--entrypoint参数可覆盖ENTRYPOINT指令)
WORKDIR
创建新容器时,在容器内部设置一个工作目录,ENTRYPOINT或CMD会在该目录下执行。(命令行-w指令可覆盖)
ENV
设置环境变量,会持久保存到镜像创建的任何容器中。(命令行-e传递环境变量)
USER
指定以什么用户去运行程序(命令行-u可覆盖)
VOLUME
向基于镜像创建的容器添加卷。可以为基于镜像的任何容器创建挂载点进行持久存储或共享数据。区别“使用卷”和“挂载卷”。
示例:VOLUME [ "/var/lib/tomcat8/webapps/" ]
ADD
用来将构建环境下的文件和目录(构建环境或者上下文)复制到镜像中去,会将文件源复制到目标地址,文件源可以是URL,也可以是压缩包(会自动解压)。
COPY
类似与ADD,只做复制(不去提取及解压),文件源必须放在Dockerfile同一目录(任何位于构建环境之外的东西都是不可用的)。
ONBUILD
为镜像添加触发器,子镜像会按照父镜像中指定的顺序执行(该命令可被继承且只能被继承一级,在子镜像中使用)。可用作镜像模板的定制化。 (问题:ONBUILD ADD添加本地源代码到镜像的操作,如果不要ONBUILD,是否也能完成?)
Docker镜像操作
将镜像推送到Docker Hub
docker push 镜像名(jamtur01/static_web)
需要加用户名,否则默认root用户(官方)无权推送。
删除镜像
docker rmi 镜像名
删除所有镜像
docker rmi `docker images -a -q`
docker内部网络
安装Docker时,会创建一个docker0虚拟网桥,用于连接容器和本地宿主网络,每个docker容器都会在该网桥上分配一个IP地址。
网络信息中还有以veth开头的网络,Docker每创建一个容器就会创建这样一组网络接口,该接口类似一根虚拟网线,一端插在容器(eth0*),一端插在docker0网桥上。
Docker容器运行参数
Dokcer容器互联
docker run --link 容器名称:连接后容器别名
启动的该容器可以访问被link容器的任意公开端口。使用 --icc==false 参数,只允许有连接的容器之间的互相通信。(被连接的容器必须运行在同一宿主机上)
为容器单独配置DNS
docker run --dns(或--dns-search)
否则默认根据宿主机信息配置DNS。
特权模式运行容器
docker run --privileged
--privileged启动Docker的特权模式,允许以其宿主机的几乎所有能力来运行容器,包括一些内核特性和设备访问(如在Docker中运行Docker)。
获取容器id并保存
docker run --cidfile
如“docker run --cidfile /tmp/containerid.txt”。
指定容器里的所有卷都加入新创建的容器里
docker run --volumes-from
卷的特性就是可以被任意容器挂载
用完即扔容器
docker run --rm
使用--rm会在容器运行完毕后自动删除容器。
设置容器的主机名
docker run -h 主机名
会覆盖默认的主机名(容器ID)
进入容器
docker attach
阻塞并等待容器命令执行完成返回
docker wait
查看容器日志
docker logs 容器名/容器ID
可查看标准输出的日志
向容器发送信号
docker kill -s 信号 容器
该操作是发送指定的信号,而不是杀掉容器。
进入容器查看环境变量
env
Docker镜像与容器的区别
Docker镜像与Docker容器的不同确实不易理解,其实本质区别如下图示。
Docker镜像是由多个镜像层叠加起来的一个(联合)文件系统,而Docker容器=Docker镜像+读写层(容器唯一区别于镜像的便是最上面那一层是可读可写的)
运行态(Running)下的容器是由一个可读写的文件系统(静态容器)+ 隔离的进程空间和其中的进程构成的。容器中的进程可能会对文件进行修改、删除、创建,这些改变都将作用于可读写层(read-write layer)。
其实到这里,我们已经知道两者大至的区别了。
说的再透一点就是:
- Docker镜像是一个只读的文件系统,它不能被修改或不能保存状态。
- 启动一个Docker容器可采用“docker run image”的方式,它会在该镜像所有的镜像层之上增加一个可写层。这个可写层有运行在CPU上的进程,而且有两个不同的状态:运行态(Running)和退出态(Exited)。当使用docker run启动容器,Docker容器就进入运行态,当我们停止Docker容器时,它就进入退出态。
- 处于运行态的Docker容器,我们对它所做的一切变更都会永久地写到容器的文件系统中(而非写入到Docker镜像中)。
- 可以用同一个镜像启动多个Docker容器,这些容器启动后都是活动的,彼此还相互隔离,对其中一个容器所做的变更只会局限于该容器本身。
参考:
《第一本Docker书》-- James Turnbull
https://www.cnblogs.com/LangXian/p/10639936.html