Docker学习【一文全解】
文章目录
1. Docker概念
-
Docker是一个开源的应用容器引擎
-
Docker是一种容器技术,解决软件跨环境迁移的问题
-
Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud(后来都改名为 Docker Inc) 公司内部的一个业余项目。基于 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。
-
Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上。
-
容器是完全使用沙箱机制,相互隔离
-
容器性能开销极低。
-
Docker 从17.03版本之后分为CE(CommunityEdition:社区版)和EE(EnterpriseEdition:企业版)
2. Docker安装
- 参看官网文档
- 参看菜鸟教程
3. Docker架构
镜像和容器的命令是最重要的两部分
4. Docker命令
4.1 服务相关命令
#查看Docker服务状态
systemctl status docker
#启动Docker服务
systemctl start docker
#重启Docker服务
systemctl restart docker
#停止Docker服务
systemctl stop docker
#开机启动Docker
systemctl enable docker
4.2 Docker镜像相关命令
-
查看镜像
docker images #查看所有镜像的id docker images -q
-
搜索镜像
docker search [镜像名] #例如redis docker search redis #访问搜索镜像,查看维护的相应的版本号 hub.docker.com
-
拉取镜像
docker pull [镜像名]:[版本号] #例如,如果不写版本号则默认是latest(最新的) docker pull redis #如果失败并提示DNS错误( No address associated with hostname) #在/etc/resolv.conf修改为nameserver 8.8.8.8
-
删除镜像
#通过id删除, id根据docker images查询获取 docker rmi [id] #通过镜像名:版本删除 docker rmi redis:5.0 #删除所有镜像 docker rmi 'docker images -q'
4.3 容器相关命令
-
查看容器
#查看正在运行中的容器 docker ps #查看所有容器 docker ps -a
-
创建容器
-
创建容器命令:docker run
-
-i:表示运行容器
-
-t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端。
-
–name :为创建的容器命名。
- –name=name1:给容器命名name1这里的=可以换为空格
-
-v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
-
-d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加-i -t两个参数,创建后就会自动进去容器)。
-
-p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射
-
-
交互式方式创建容器
#这里的/bin/bash是一个伪终端(centos是bash,sh的命令终端太过简陋了),也可以是/bin/sh,因为带有参数t docker run -it --name=容器名称 镜像名称:版本 /bin/bash #退出当前容器 exit
-
守护式方式创建容器
docker run -di --name=容器名称 镜像名称:版本 #登录守护式容器方式 docker exec -it 容器名称 (或者容器ID) /bin/bash
-
-
启动容器
docker start 容器名称(或者容器ID)
-
停止容器
docker stop 容器名称(或者容器ID)
-
删除容器
docker rm 容器名称(容器ID)
-
查看容器信息
docker inspect 容器名称(容器ID)
5. Docker容器的数据卷
-
引入数据卷的原因
- Docker容器删除之后,在容器中产生的数据也会随之销毁
- Docker容器和外部机器之间不能直接交换文件
- 容器之间无法进行数据交互
-
数据卷是宿主机中的一个目录或文件
- 当容器目录和数据卷目录绑定后,对方的修改会立即同步
- 一个数据卷可以被多个容器同时挂载
-
数据卷的作用
- 容器数据持久化
- 外部机器和容器间接通信
- 容器之间数据交换
-
数据卷小结
5.1 配置数据卷
-
创建启动容器时,使用-v参数设置数据卷
#注意事项: #1.目录必须是绝对路径 #⒉.如果目录不存在,会自动创建 #3.可以挂载多个数据卷 docker run ... -v 宿主机目录(文件):容器内目录(文件) ... #例如 docker run -it --name=c1 -v /root/data:/root/data_container centos:7 /bin/bash/ #挂载多个 docker run -it --name=c1 -v /root/data:/root/data_container -v /root/data1:/root/data_container1 centos:7 /bin/bash/
5.2 数据卷容器
- 方便多个容器内数据交互
-
创建启动c3数据卷容器,使用-v参数 设置数据卷
docker run -it --name=c3 -v /volume centos:7 /bin/bash
-
创建启动c1 c2容器,使用–volumes-from参数设置数据卷
#将c1、c2和c3都挂载到了同一个数据卷上 docker run -it --name=cl --volumes-from a3 centos:7 /bin/bash docker run -it --name=c2 --volumes-from a3 centos:7 /bin/bash
6.Docker应用部署
6.1 MySQL部署
-
在Docker容器中部署MySQL,并通过外部MySQL客户端操作MySQL
- 搜索mysql镜像
- 拉取镜像
- 创建容器
- 操作容器中的mysql
-
注意
-
外部数据和容器中的数据不互通
-
容器内的网络服务和外部机器不能直接通信
-
可以通过将容器内得端口映射到宿主机的端口上,再通过外部机器访问宿主机的端口从而间接访问到容器的服务,这种操作称为:端口映射
- 容器内部的端口可以和宿主机的端口相同,因为从某种意义而言容器就是一个新的(伪)主机
-
-
部署MySQL
-
在hub.docker.com中搜索mysql查看可用的版本
-
拉取镜像
# 我这里安装mysql8.0的 docker pull mysql:8.0
-
创建容器,设置端口映射、目录映射
# 创建了一个专门存放容器数据的文件夹 # /home/docker_container_data/mysql # -i:运行,-d以守护者的方式运行, \:命令未输完,下一行继续输入 docker run -id \ -p 33306:3306 \ --name=docker_mysql \ -v /home/docker_container_data/mysql/conf:/etc/mysql \ -v /home/docker_container_data/mysql/logs:/logs \ -v /home/docker_container_data/mysql/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=aQ2:pJ1\!wL1 \ mysql:8.0
- 参数说明
- -p 33306:3306,将容器的3306端口映射到宿主机的33306上
- -v ,将容器的/etc/mysql/conf.d挂载到宿主机的/home/docker_container_data/mysql/conf下
- -e MYSQL_ROOT_PASSWORD=aQ2:pJ1\!wL1$, 初始化root用户的密码
- 一定注意这里的密码是aQ2:pJ1!wL1而\是为了转义!,在bash中!是一种命令
- :和=等符号两边不能有多余的空格
放开服务器端口33306,此后就可以在外部通过端口33306登录这台服务器上Docker容器中的MySQL了
- 参数说明
-
登录容器
docker exec -it docker_mysql /bin/bash
-
7. Dockerfile
7.1 Docker 镜像原理
-
引入
- Docker镜像的本质?
- 一个分层的文件系统
- Docker中的一个centos镜像只有区区200MB,而一个实际的centos操作系统要数个G?
- Docker中的centos镜像复用宿主机操作系统的bootfs,自身只有rootfs和其他镜像
- DOcker中一个tomcat镜像有500MB,而一个tomcat安装包只有70+MB
- tomcat虽然只有70+MB,但是因为Docker分层的问题,它需要依赖父镜像和基础镜像,对于用户而言看到的整个镜像就是500+MB了
- Docker镜像的本质?
-
linux文件系统由bootfs和rootfs两部分组成
-
bootfs:包含bootloader(引导加载程序)和kernel(内核)
-
rootfs:root文件系统,包含的就是典型的linux系统中de/dev、/proc、/bin和/etc等标准目录和文件
-
不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu、centos等
-
-
Docker镜像原理
-
Docker镜像是由特殊的文件系统叠加而成的
-
最低端是bootfs,一般使用宿主机的bootfs
-
第二层是root文件系统rootfs,成为base image
-
再往上可以叠加其他的镜像文件nginx、mysql等等
-
统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,并为这些层提供一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。
- 如下图,对于用户而言就只是一个tomcat镜像,但实际确实由bootfs+rootfs+jdk+tomcat才组成的(不过bootfs是复用宿主机操作系统的,在此不占空间),这也解释了为什么一个70+MB的tomcat在Docker镜像中最终有500+MB
-
一个镜像可以放在另一个镜像上面。位于下面的镜像称为父镜像,最底部的镜像为基础镜像
-
当一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器。可以通过其来修改制度镜像,修改完成之后保存为一个新的镜像。
-
复用,在Docker中是一种很重要的思想,这也是Docker文件系统这也分层的好处。
-
7.2 镜像制作
-
容器转为镜像
# 容器转为镜像 docker commit [容器id] [新镜像名称]:[版本号] # 镜像压缩, 因为镜像无法传输,所以需要打成压缩包,才能传输 docker save -o [压缩文件名称] [镜像名称]:[版本号] # 将压缩包还原为镜像。 docker load -i [压缩文件名称]
7.3 Dockerfile概念及作用
- Dockerfile概念
- Dockerfile 是一个文本文件
- 包含了一条条的指令
- 每一条指令构建一层,基础镜像,最终构建出一个新的镜像
- 对于开发人员:可以为开发团队提供一个完全一直的开发环境
- 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作
- 对于运维人员:在部署时,可以实现应用的无缝移植
7.4 Dockerfile关键字
- 部分常用关键字及其作用
- MySQL8.0的Dockerfile
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定父镜像 | 指定dockerfile基于那个image构建 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
LABEL | 标签 | 用来标明dockerfile的标签,可以使用Label代替Maintainer最终都是在docker image基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令默认是/bin/sh格式: RUN command或者RUN[“command”, “param1”,“param2”] |
COPY | 复制文件 | build的时候复制文件到image中 |
ENV | 环境变量 | 指定build时候的环境变量可以在启动的容器的时候通过-e覆盖格式ENVname=value |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口启动容器的使用-p来绑定暴露端口格式:EXPOSE 8080或者EXPOSE 8080/udp |
USER | 指定执行用户 | 指定build或者启动的时候用户在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令基本上没用因为很多时候应用本身有健康监测机制 |
WORKDIR | 工作目录 | 指定容器内部的工作目录如果没有创建则自动创建如果指定/使用的是绝对地址 如果不是/开头那么是在上—条workdir的路径的相对路径 |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
CMD | 容器启动命令 | 提供启动容器时候的默认命令和ENTRYPOINT配合使用. 格式CMDcommand param1 param2 或者CMD [“command”,“param1”,“param2”] |
-
写好dockerfile之后
#通过命令构建镜像 docker build -f [dockerfile文件] -t [新的镜像名称]:[版本]
-
Dockerfile 运行Springboot案例
8. Docker 服务编排
8.1 服务编排概念
- 服务编排:按照一定的业务规则批量管理容器
- 如果没有服务编排,那么可能会遇到需要启动很多次容器的问题
8.2 Docker Compose 概述
-
Docker Compose:一个编排多容器分布式部署的工具,提供命令集管理容器化应用的完整开发周期,包括服务构建,启动和停止。使用步骤:
-
利用Dockerfile定义运行环境镜像
-
使用Docker-compose.yml定义组成应用的各服务
-
运行docker-compose up 启动应用
-
8.3 案例
-
创建目录
-
在目录里新建一个
docker-compose.yml
文件(文件名唯一)version:'3' # 版本号 services: nginx: # 这个名字可以自己取 image: nginx # 镜像名称,可加上版本nginx:5.0 ports: - 80:80 # 宿主机端口:容器端口 links: - app # 当前这个nginx项目可以连接在app这个项目 volumes: - ./nginx/conf.d:/etc/nginx/conf.d #数据挂载,可以设置多个 app: image: app # 这个app是之前已经创建好的镜像 expose: - "8080" # 向外暴露的端口
-
在宿主机创建
mkdir -p ./nginx/conf.d
,因为nginx目录也没有所有加上-p可以直接创建多层目录 -
在
./nginx/conf.d
目录下 编写nginx.conf配置文件server { listen 80; # 关闭日志 access_log off; location / { # 反向代理 访问80端口的时候,会导向http://app:8080 proxy_pass http://app:8080; } }
-
运行
# 前台运行,日志打印在终端 docker-compose up # 后台运行,看不到日志不打印在终端 docker-compose up -d