虚拟机:虚拟一套完整的操作系统【软件+硬件】,最后在操作系统上安装应用程序
docker:不模拟完整的操作系统,更不会虚拟硬件,只将软件运行需要的资源打包到容器中,应用程序直接通过docker引擎和宿主机操作系统的内核进行交换【docker和宿主机共享一个操作系统】
docker容器之间相互隔离,每个容器都有自己的文件系统,容器之间进程互不影响
DevOps:开发自运维
Docker必须在6.5版本及其以上的CentOS运行
docker的三大要素:镜像 image、容器 container、仓库
镜像就是类, 相当于一个只读的模板,容器就是对象
容器是用镜像文件创建的运行实例,一个镜像可以创建多个容器
仓库是集中存储镜像文件的地方,分为公开库和私有库,最大的公开库docker hub,存放了大量的镜像,一般国内都用阿里云、网易云
Registry:注册服务器
一个Registry上有多个Repository,一个仓库中包含了多个镜像,一个镜像可以创建多个容器,一个容器运行一种服务
每个镜像有不同的标签tag
Docker是一个管理引擎,是容器运行的载体
RHEL:Red Hat Enterprise Linux 红帽企业版linux系统
CentOS:开源版的红帽企业版linux系统
Fedora:费多拉 开源版的红帽个人版linux系统
EPEL:用于为红帽系操作系统提供软件包
EPEL的使用:安装epel-release的软件包,这个软件包会自动配置yum的软件仓库
见官网,安装好将docker的镜像仓库设置为阿里云的
systemctl start docker //启动docker
systemctl stop docker //停止docker
systemctl restart docker //重启docker
docker是个client-service结构的系统, docker的守护进程daemon运行在主机上,然后通过socket从客户端连接到主机上,守护进程从客户端接收命令并管理运行在主机上的容器,注意:所有命令都要经过守护进程
vim /etc/docker/daemon.json
--------------------------------------------------------------------------------
# 配置内容
{
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
# 执行命令生效
systemctl daemon-reload
systemctl restart docker
查看dokcer版本:docker version
查询docker的完整信息:docker info
docker帮助命令:docker --help
docker images:本地镜像仓库的镜像列表
docker images -a:显示本地仓库的全部镜像(包含中间层镜像)
docker images -q:只显示镜像的唯一标示ID
docker images --digests:显示镜像列表中包含镜像的摘要信息
docker images --no-trunc:显示完整的镜像信息
镜像的仓库源 镜像的版本标签 镜像的唯一标示 镜像的创建时间 镜像的大小
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 9 months ago 1.84kB
同一仓库源有多个TAG,代表这个仓库源的不同版本,我们使用 REPOSITORY:TAG 来表示不同的镜像
如果不指定镜像的版本标签,默认版本标签为:lastest,即REPOSITORY:lastest
(1)docker search 镜像名称:到https://hub.docker.com上去查询镜像
【即使本地配置镜像仓库为阿里云,但仍然到https://hub.docker.com上去进行查询】
docker search --filter=stars=50 镜像名称:到https://hub.docker.com上去查询点赞数超过50的镜像
docker search --filter=stars=30 mysql
(2) docker pull 镜像名称[:tag] 到本地指定的镜像仓库拉取镜像,不指定tag版本号,默认使用latest版本
(3) docker rmi 镜像名称[:tag]或镜像id 删除本地镜像,不指定tag版本号,默认使用latest版本
docker rmi -f 镜像名称[:tag] 或镜像id 强制删除本地镜像, 即使容器正在使用该容器
其中i表示image
(4) docker rmi -f 镜像名1[:tag] 镜像名2[:tag] 删除多个本地镜像
(5) docker rmi -f $(docker -aq) 删除本机所有镜像 $()是linux命令
创建并进入运行的容器
docker run -it 镜像名称或镜像id 作用:在docker的容器中运行指定镜像
其中:-i以交互模式运行,让容器的标准输入保持打开
-t:为容器重新分配一个伪终端,并绑定到容器的标准输入上 【通常it一起使用】
--name:为容器指定名称 如果不指定,则自动随机生成一个
-P:随机端口映射
-p:指定端口映射,有以下四钟格式【docker容器的端口和宿主机的映射关系】
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort
修改端口号映射:/var/lib/docker/containers/容器完整的id目录下的json文件中记录了端口,修改后重启
在前台运行容器:docker run -it 镜像名称或镜像id --name 容器名称
在后台运行容器:docker run -d 镜像名称或镜像id
docker后台运行,必须有一个前台进程。
容器运行的命令如果不是那些一直挂起的命令(如:top、tail),就会自动退出,因此docker执行后台运行命令后,无前台进程,执行docker -ps看不到正在运行的进程
举例:
docker run -d 0f3e07c0138f /bin/sh -c “while true;do echo 123;sleep 2;done”
-d:在后台运行,上述命令通过死循环来让容器在后台持续运行,不会因为前台无进程而自杀
0f3e07c0138f:镜像id,也可以是镜像名称
sh -c:让 bash 将一个字串作为完整的命令来执行
查看容器状态
docker logs -tf 容器id/容器名称: 查看容器的运行日志
其中:-t:显示时间戳 -f:跟踪日志,实时显示新增日志 follow
docker top 容器id/容器名称: 查看容器内运行的进程
docker inspect 容器id/容器名称:查看容器内部的详细信息
docker ps 查看docker当前正在运行的容器
docker ps -a 查看docker正在运行的容器和历史上运行过的容器
docker ps -l 查看docker最近创建的容器
docker ps -n 3 查看docker最近创建的3个容器
docker ps -q 静默模式,只显示容器编号
docker ps --no-trunc 不截取输出正在运行的进程信息
容器有有7种状态:created(已创建)|restarting(重启中)|running(运行中)|removing(迁移中)|paused(暂停)|exited(停止)|dead
docker ps命令执行后可以看到以下信息:
CONTAINER ID b8b43fa57cd6 容器唯一标识
IMAGE centos 创建容器使用的镜像
COMMAND "/bin/bash" 启动容器时运行的命令
CREATED 7 minutes ago 创建容器的时间
STATUS Up 37 seconds 容器现在的状态
PORTS 端口号容器的端口信息和使用的连接类型
NAMES mycentos 容器的名称【可以自定义,也可以默认】
1.容器的两种退出方式
容器停止退出命令:exit
容器不停止退出快捷键:ctrl+p+q
从宿主机进入正在运行的容器: docker attach 容器id/容器名
使运行的容器执行指定命令而不进入容器,在容器外就可以查看结果:docker exec -it 容器id/容器名 命令行
举例:docker exec -it 6562e3d32b3a ls /home -lha
2.停止容器
docker stop 容器id/容器名称 【容器id通过docker -ps查看】
3.强制停止
docker kill 容器id/容器名称
4.启动容器
启动容器:docker start 容器id/容器名称 【容器id通过docker ps -l查看】
重启容器:docker restart 容器id/容器名称 【容器id通过docker -ps查看】
5、删除已停止的容器
docker rm 容器id/容器名称
docker rm 容器id/容器名称
docker rm $(docker ps -aq):删除所有容器
docker rm 容器id1/容器名称1 容器id2/容器名称2:删除多个容器
6.删除运行中的容器
docker rm -f 容器id/容器名:强制删除运行中的容器
7.复制容器内的文件到宿主机
docker cp 容器id/容器名:容器内文件路径 宿主机本地目录路径
8.复制宿主机文件路径到容器内的目录下
docker cp 宿主机本地文件路径 容器id/容器名:容器内目录路径
UnionFS(联合文件系统):分层、轻量级的文件系统,支持对文件系统的修改作为一次提交来层层叠加
特性:一次同时加载多个文件系统,但表面看起来只是一个文件系统,实际是果果文件系统的叠加
docker镜像由一层一层的联合文件系统组成,docker镜像的最底层是bootfs(boot file system),与宿主机共用
linux系统包含bootfs和rootfs
bootfs主要包含bootloader和kernel,其中bootloader负责引导加载kernel。启动时加载bootfs,加载完成后整个kernel就在内存中了,内存使用权就交给内核,此时卸载bootfs
rootfs:在bootfs上是rootfs,包含linux系统中各种标准目录
**镜像采用分层文件系统的原因:**共享资源
多个镜像都从相同的base镜像构建而来,宿主机只需在磁盘保存一份base镜像就行了,而内存只需加载一份base镜像,其他镜像也可以共用
镜像是只读的,不能修改
**docker commit的作用:**将标准的镜像文件在容器中运行起来后,自定义配置后,提交容器副本后使之成为一个自定义镜像,存放在本地镜像仓库
docker commit -m="提交的描述信息" -a="作者" 容器id 创建的新镜像的名称:[标签名]
容器内应用程序产生的数据只能保持中容器内,通过生成镜像保持起来,否则容器删除后就不存在了,因此需要数据卷
dokcer数据卷实际是将宿主机的目录挂载到docker容器,因此如果容器有相同目录,宿主机目录会覆盖容器目录
容器数据卷的作用:(1)数据持久化 (2)不同容器之间的数据共享
docker run -it -v 宿主机目录路径A:容器内目录路径B 镜像id/镜像名
如果需要挂载多个容器卷,则使用多个-v,其中:v是volume的简写,后面跟宿主机目录和容器内目录的映射关系
注意:【如果目录已经存在,执行时会覆盖原目录】
如果host机器上的目录不存在,docker会自动创建该目录
如果container中的目录不存在,docker会自动创建该目录
如果container中的目录已经有内容,那么docker会使用host上的目录将其
(1)添加后,在主机修改文件,容器内也会发生变化;容器进行修改,宿主机也会发生变化
(2)容器停止后,宿主机修改文件,容器重启后也会同步修改的数据
(3) A是在主机上的地址,B是在容器中的地址,这两个地址如果不存在都会创建,一旦容器运行,AB的会完全同步。
覆盖掉
docker volume ls可以看到当前所有的volume
docker volume inspect [volume name] 获取指定volume在docker 虚拟机中的位置
docker volume create --name 容器数据卷名称 指定容器数据卷的名称,如果不指定时,创建容器时会自己生成一串很长的名称
通过docker inspect 容器id/容器名 可以查看绑定信息
"Mounts": [
{
"Type": "bind",
"Source": "/home/share", //宿主机目录
"Destination": "/share/data",//容器内目录
"Mode": "",
"RW": true,//容器对挂载容器卷目录的权限,此处为读写操作均支持
"Propagation": "rprivate"
}
]
docker run -it -v 宿主机目录:容器内目录:ro 容器id/容器名
ro:表示只读操作readonly
"Mounts": [
{
"Type": "bind",
"Source": "/home/share",
"Destination": "/home/share",
"Mode": "ro",
"RW": false, //此时为false
"Propagation": "rprivate"
}
]
在宿主机上编写Dockerfile,挂载数据卷到父镜像
**Dockerfile不指定宿主机目录的原因:**dockerfile命令是创建镜像的,因此VOLUME指令只能定义容器内目录【能同时指定多个】,宿主机目录无法指定,因为宿主机有哪些目录是无法确定的
#volume test
From centos //指定底层使用centos
VOLUME ["容器内目录1","容器内目录2"]
CMD echo "创建成功"
CMD /bin/bash 如果没有这个命令,容器创建成功后无法直接进入容器,需要在创建命令后加/bin/bash
2.创建镜像
docker build -f dockerfile文件的路径 -t 镜像名称:[镜像版本] dockerfile文件所在目录
其中-f:指定dockerfile文件的路径,-t tag:表示镜像的名称和版本
如果不使用 -f,则默认将上下文路径下的名为 Dockerfile 的文件认为是构建镜像的 "Dockerfile"
docker build -t 镜像名称:[镜像版本] Dockerfile文件所在目录
docker build -f dockerfile文件的路径 -t 镜像名称:[镜像版本]
3.根据镜像创建容器
docker run -it 镜像id/镜像名 /bin/bash
如果创建挂载数据卷的镜像时没有指定命令:CMD /bin/bash 需要在创建容器的命令后面加/bin/bash
如果新添加的容器没有写权限,则只执行下面的命令添加权限:
docker run -it --privileged=true 镜像id/镜像名 /bin/bash
4.查看数据卷的默认映射关系
docker inspect 容器id/容器名称
"Mounts": [
{
"Type": "volume",
"Name": "c361f213dc49570847056c2e42f61fa12e0c673ab74cafd45dba19e97c023d94",
"Source": "/var/lib/docker/volumes/c361f213dc49570847056c2e42f61fa12e0c673ab74cafd45dba19e97c023d94/_data", //容器目录映射的宿主机目录
"Destination": "/home/a", //容器目录
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "e2c560f3dfe13fd4802ee3e1e266b4a7b72ef4504cb79e4907646ef58256e5d4",
"Source": "/var/lib/docker/volumes/e2c560f3dfe13fd4802ee3e1e266b4a7b72ef4504cb79e4907646ef58256e5d4/_data",
"Destination": "/home/b",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
数据卷容器:
容器A已经挂载了数据卷,其他容器通过挂载这个父容器A来实现数据共享,挂载数据卷的容器A称为数据卷容器
1.启动已经挂载了数据卷的父容器
docker run -it --name parent 镜像id/镜像名
2.挂载父容器
docker run -it --name 子容器的名称 --volumes-from 父容器的id或名称 镜像id/镜像名称
3.在父容器或子容器挂载的数据卷中,修改后其他容器中也能看到,从而实现数据共享
**重点:**父容器被停止、删除后,不影响子容器继续使用继承的数据卷,甚至新建容器来继承子容器的数据卷
Dockerfile
Dockerfile是用来构建镜像的文件,是由一系列命令和参数构成的脚本
**镜像的构建三部曲:**编写Dockerfile→docker build→docker run
Dockerfile由四部分构成:基础镜像信息、维护者信息、镜像操作指令、容器启动时的执行指令
(1)Dockerfile中以#
字符开头则被视为注释
(2)保留字必须全部大写,且后面必须跟一个参数
(3)指令是从上到下顺序执行的
(4)每条指定都会创建一个新的镜像层,并对镜像进行提交
Dockerfile的执行流程:
Dockerfile指令
FROM:指定当前要创建的镜像是基于哪个基础镜像 第一条指令必须是FROM
MAINTAINER:镜像维护者的姓名和邮箱地址
**RUN:**容器构建时需要运行的指令 【 每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像】
**EXPOSE:**容器暴露的端口号
**WORKDIR:**容器运行后通过终端登录容器后,进入的第一个工作目录
**ENV:**指定环境变量 【ENV 环境变量名 指定路径】 【指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持】
VOLUME:指定容器数据卷 【VOLUME [“容器内目录1”,“容器内目录2”,…]】
**ONBULID:**当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。基于 image-A 创建新的镜像时,新的Dockerfile中使用 FROM image-A指定基础镜像时,在build新镜像时执行父镜像的ONBUILD 指令内容
ADD和COPY的区别:
ADD:【ADD 源文件路径 目的目录路径】 将宿主机的源文件复制到容器中的指定目录,并解压文件
COPY:【COPY 源文件路径 目的目录路径】将宿主机的源文件到容器中的指定目录
CMD和ENTRYPOINT的区别:
**CMD:**指定一个容器刚启动时要运行的命令
注意:
每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。
用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令
【docker run -it 镜像id/镜像名 /bin/bash,其中/bin/bash就是指定的启动运行命令】
**ENTRYPOINT:**指定一个容器刚启动时要运行的命令
注意:
每个Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。
用户启动容器时候指定了运行的命令,不会覆盖掉 CMD 指定的命令,而是在CMD指定的命令后追加参数
FROM centos
MAINTAINER liuwei
ENV mypath /root
WORKDIR $mypath
RUN yum install -y vim
RUN yum install -y net-tools
#子镜像继承此镜像时,编译自镜像时触发此命令执行
ONBUIlD RUN echo "============================================"
ENTRYPOINT curl -s https://ip.cn
docker run -it ipcentos -i
{"ip": "47.104.5.223", "country": "山东省青岛市", "city": "阿里云"}
Base镜像(scratch):Docker hub中大部分的镜像都是基于base镜像构建的
自定义Centos
docker hub上的官方centos是不支持ifconfig和vim的
1.编写Dockerfile文件
FROM centos
MAINTAINER:liuwei
ENV mypath /root
WORKDIR $mypath
RUN yum install -y vim
Run yun install -y net-tools
CMD /bin/bash
2.构建build
docker build -t 新镜像名:版本号 Dockerfile的当前路径
3.运行run
docker run -it 镜像名:版本号
查看镜像的变更历史
docker history 镜像id/镜像名
详细安装见:https://hub.docker.com//mysql
docker search mysql
docker pull mysql
创建运行容器之前,先将容器中/etc/mysql目录下的my.cnf文件,复制到容器外的指定目录
docker run --name db_master -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456nw --privileged=true --restart=unless-stopped \
-v /etc/localtime:/etc/localtime:ro \
-v /docker/master/conf/my.cnf:/etc/mysql/my.cnf:rw \
-v /docker/master/data:/var/lib/mysql:rw -d 7a3923452254[镜像名或id]
----------------------------------------------------------------------
#定义存储引擎
default-storage-engine = INNODB
#定义服务器字符集和排序规则,在创建数据库和表时不特别指定字符集,这样统一采用character-set-server字符集和collation-server排序规则
character-set-server= utf8mb4
collation-server = utf8mb4_unicode_ci
#定义默认时区
default-time_zone='+8:00'【linux服务器时区必须一致】
----------------------------------------------------------------------
--restart: no – 容器退出时,不重启容器;
on-failure – 只有在非0状态退出时才从新启动容器;
always – 无论退出状态是如何,都重启容器;
-p:指定宿主机和docker的映射端口号
-v:挂载容器数据卷
-e:设置环境变量,MYSQL_ROOT_PASSWORD是mysql数据库的用户密码环境变量,这里用于指定初始密码
-d:后台运行
4.进入安装mysql的容器
docker exec -it 容器id/容器名 /bin/bash
5.docker检查容器是否运行正确
#容器ID,容器的源镜像,启动命令,创建时间,状态,端口映射信息,容器名字
docker container ls
6.从容器内连接mysql,mysql默认已经配置安装路径到环境变量
# mysql 8数据库设置远程访问和加密方式
mysql -uroot -p
show databases;
use mysql;
select user,host from user;
#设置远程连接,将host设置为%,允许所有ip访问
update user set host="%" where user="root";
#重新加载权限表
flush privileges;
#设置密码和密码加密方式
ALTER USER 'root'@'%' IDENTIFIED WITH caching_sha2_password BY '3927493nw';
docker服务的自启动设置
部署项目服务器时,为了应对停电等情况影响正常web项目的访问,会把Docker服务设置为开机自动启动:
systemctl enable docker.service
docker容器的自启动设置
在运行docker容器时可以加如下参数来保证每次docker服务重启后容器也自动重启:
--restart=always
no – 容器退出时,不重启容器;
on-failure – 只有在非0状态退出时才从新启动容器;
always – 无论退出状态是如何,都重启容器;
unless-stopped 如果容器正常stopped,然后机器重启或docker服务重启,这种情况下容器将不会被restart
如果已经启动了docker容器则可以使用如下命令:
docker update -–restart=always 容器id/容器名 【注意:如果要linux重启后容器自启动,则需要docker run时时不带命令,最后一个命令默认是启动命令】
还可以在使用on - failure策略时,指定Docker将尝试重新启动容器的最大次数。默认情况下,Docker将尝试永远重新启动容器。
sudo docker run -–restart=on-failure:重启最大次数 容器id/容器名
防火墙和端口
firewall-cmd内置了常用的一些服务,可以在/usr/lib/firewalld/services里面看到,如果想启用默认服务的话(以允许http服务为例):
firewall-cmd --add-service=http --permanent //--permanent表示永久生效,不加这个参数的话只会针对本次执行完命令生效,重启后就不管用了
firewall-cmd --add-port=80/tcp --permanent //添加端口号80
firewall-cmd --reload //重新加载firewall配置,很关键~不然也不生效
查看开放的端口号:firewall-cmd --list-all
启动/重启/关闭/重启防火墙:systemctl start/restart/stop/reload firewalld
查看防火墙状态:systemctl status firewalld
(1)停止容器与docker服务
docker stop 容器id systemctl stop docker
(2)修改该容器中的目录下的hostconfig.json文件
sudo vim /var/lib/docker/containers/容器hash/hostconfig.json
(3)重启docker服务和容器
firewalld 与 iptables 都是 linux 中防火墙的管理工具,实现方式不一样,但防火墙功能是由位于内核中的netfilter实现的
iptables 仅能通过命令行进行配置;而 firewalld 提供了图形接口
iptables 通过控制端口来控制服务,而 firewalld 则是通过控制协议来控制端口
docker中 启动所有的容器命令
docker start $(docker ps -a | awk ‘{ print $1}’ | tail -n +2)
docker中 关闭所有的容器命令
docker stop $(docker ps -a | awk ‘{ print $1}’ | tail -n +2)
docker中 删除所有的容器命令
docker rm $(docker ps -a | awk ‘{ print $1}’ | tail -n +2)
docker中 删除所有的镜像
docker rmi $(docker images | awk ‘{print $3}’ |tail -n +2)
安装Docker之后,Docker守护进程会监听Unix域套接字:/var/run/docker.sock,容器中的进程可以通过套接字与Docker守护进程进行通信,而Portainer通过绑定的/var/run/docker.sock文件与Docker守护进程通信,执行各种管理操作
docker run -p 9000:9000 \
--name portainer --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /docker/portainer/data:/data \
-d portainer/portainer
docker system df:查看docker磁盘使用情况
docker system prune:用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)