Docker基础
官方文档地址:https://www.docker.com/get-started 推荐
中文参考手册:https://docker_practice.gitee.io/zh-cn/中文gitee
什么是Docker
1.官网定义:
我们帮助开发人员和开发团队构建和发布应用
我们为你提供一个完整的容器解决方案,不管你是谁,不管你在哪里,你都可以开始容器的旅程
docker是一个容器技术,docker引擎容器(container)软件(redis mysql tomcat rabbitmq) 构建发布应用
通俗理解为docker是一个软件容器平台|引擎|技术|
早期docker定义:运行你的应用不需要你的环境
容器到底装的是什么?
容器装的就是一个个的软件服务
Docker优势
环境一致,高效迁移
如:我们一个web应用程序涉及很多东西,比如django、mysql、redis、nginx等软件环境,当这些其中某一项版本不一致的时候,可能就会导致应用程序跑不起来的情况,Docker则将程序以及使用软件环境直接绑定在一起,无论在哪个机器上保证的环境的一致。
进程级隔离,容器独立
如:服务器自己的程序挂了,结果发现是别人程序错误把内存吃完了,自己程序因为内存不够就挂掉了,这种也是很常见的情况,如果你的程序的重要性不是非常高的话,公司基本上不可能让你的程序独享一台服务器,这时候你的服务器就会跟公司其他人的程序共享一台服务器,所以不可避免就会受到其他程序的干扰,导致自己的程序出现问题。Docker就能很好的解决环境隔离的问题,别人程序不会影响到自己的程序。
镜像机制,便于部署
公司要弄一个活动,可能会有大量的流量进来,公司需要多部署几十台的服务器,在没有docker的情况下,要在几天内部署几十台服务器,这对运维人员来说非常的折磨,而且每台服务器的环境还不一定一样,就会出现各种问题,用Docker的话,我们只要将程序打包到镜像,你要多少台服务,我就给跑多少个容器,极大地提高了部署效率。
Docker和虚拟机的区别
每一个容器是操作系统之间的隔离
Docker 引擎的安装
安装docker引擎
linux发行版本 centos7+
安装步骤
官网安装步骤:https://docs.docker.com/engine/install/centos/
通用方式安装:跟linux的发行版本无关
Linux平台下Docker的通用方式安装方法
$ curl -fsSL get.docker.com -o get-docker.sh # 执行下载docker引擎的脚本文件
$ sudo sh get-docker.sh --mirror Aliyun # 执行脚本通过脚本下载,设置阿里云镜像下载加速
启动docker
$ sudo systemctl enable docker # 将docker加入开机自启动列表
$ sudo systemctl start docker # 启动docker服务(restart重启 status状态 stop停止)
创建docker用户组
$ sudo groupadd docker
将当前用户加入到docker组
$ sudo usermod -aG docker $USER # 修改过程中会自动创建docker
测试docker安装是否正确
$ docker run hello-world
查看docker引擎
$ docker info # 查看docker信息
$ docker version # 查看docker版本
Docker中的核心概念
镜像(image)
定义:一个镜像代表一个软件
容器 (container)
定义:一个镜像运行一次就会生成一个容器,容器就是一个运行的件服务
仓库(Respostory)
定义: 仓库用来存储所有软件的镜像位置 =====>仓库web界面 docker hub 中心仓库
本地仓库
定义:用于存储在使用docker过程中的相关镜像
Docker中核心架构图
镜像
:一个镜像代表一个应用环境,它是一个只读的文件,如:mysql镜像,tomcat镜像,redis镜像,nginx镜像等。容器
:镜像每次运行之后就是产生一个容器,就是正在运行的镜像,特点是可读可写。仓库
:用来存放镜像的位置,类似与maven仓库,也是镜像下载和上传的位置。dockFile
:docker生成镜像配置文件,用来书写自定义镜像的一些配置tar
:一个镜像打包的文件,日后可以还原成镜像
镜像加速
docker运行流程
如何拉取官方镜像
$ docker pull tomcat # 拉取最新版本的tomcat
$ docker pull tomcat:8.0 # 拉取指定版本的tomcat
Docker如何配置阿里云的镜像加速
- 进入阿里云的官方网站
- 使用账号名和密码进行登录或者扫码登录
- 在控制台搜索镜像加速服务
访问阿里云登录自己账号查看docker镜像加速服务
$ sudo mkdir -p /etc/docker $ sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["<https://xnan2sz4.mirror.aliyuncs.com>"] } EOF $ sudo systemctl daemon-reload $ sudo systemctl restart docker
验证docker的镜像加速是否生效
$ docker info ........... 127.0.0.0/8 Registry Mirrors: '<https://lz2nib3q.mirror>,aliyuncs.com' Live Restore Enabled: false Product License: Commounity Engine
概念
- docker中的三个概念
- 仓库
- 远程仓库:docker公司在世界范围内维护的一个中心,用来集中管理docker中的镜像----->搜索仓库 docker hub
- 本地仓库:用来存储自己使用过的镜像,在中心仓库下载镜像存储到本地仓库 /var/lib/docker
- 镜像 image
- 镜像是只读的,不能进行写操作
- 容器 container
- 容器可读可写
- 仓库
docker第一个应用程序
# hello-world
$ docker run hello-world
通过docker第一个程序总结docker执行流程
docker run
执行镜像 首先去本地仓库去查找,如果本地仓库有,自动对镜像生成一个容器,如果本地仓库没有,它会去中心仓库去下载到本地仓库,然后对镜像生成一个容器。
docker中镜像的相关操作
辅助命令:docker version
功能:用来查看docker客户端引擎和server端引擎版本信息
辅助命令:
docker info
功能:用来查看docker引擎
辅助命令:
docker --help
功能:帮助信息
镜像 image
查看当前本地仓库存在哪些镜像
docker image ls
或者docker images
$ docker images # 结果解释 `REPOSITORY` 镜像名称 `TAG` 镜像版本 `IMAGE ID` 镜像ID `CREATED ` 镜像创建时间 `SIZE` 镜像大小 REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 10 months ago 13.3kB tomcat 8.0 ef6a7c98d192 3 years ago 356MB
注意:以后在使用镜像时,可以使用镜像的ID短名去使用
查看当前本地仓库指定的镜像有哪些版本
docker images 镜像名
$ docker images tomcat
展示出所有的docker镜像
docker images -a
$ docker images -a
展示出所有docker镜像的ID
docker images -q
$ docker images -q # 展示内容为镜像的ID feb5d9fea6a5 ef6a7c98d192
下载一个镜像
docker pull
镜像名称 或者docker pull
镜像名称:版本$ docker pull tomcat # 获取最新版本 $ docker pull tomcat:9.0 # 获取指定版本
搜索镜像
docker search
镜像名称$ docker search tomcat # 智能查看当前镜像是否存在,不能列出版本
删除镜像
docker image rm
镜像名称(name:tag)或者docker image rm
镜像ID# 正常删除 $ docker image rmi tomcat:9.0 $ docker image rmi ef6a7c98d192 # 强制删除 $ docker image rmi -f tomcat:9.0 $ docker image rmi -f ef6a7c98d192 # 删除指定镜像名称的所有镜像---->批量删除 $ docker image rmi -f $(docker images tomcat -q) # 删除仓库内的所有镜像 $ docker image rmi -rf $(docker images -q)
清理镜像
$ docker image prune
支持的子命令
- a 删除所有没有用的镜像,而不仅仅是临时文件。
- f 强制删除镜像文件,无需弹出提示确认。
docker中容器的基本操作1
操作容器的命令格式: docker 命令 [选项]
如何查看docker引擎中运行的容器有哪些?
docker ps
查看当前docker引擎中正在运行的容器$ docker ps # 结果解释 `CONTAINER ID` 容器ID `IMAGE` 基于哪个镜像 ` COMMAND` 容器内启动服务的命令 `CREATED` 容器创建时间 `STATUS` 容器状态 `PORTS` 容器服务监听端口 `NAMES` 容器名称 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6f755ceba23c tomcat:8.0 "catalina.sh run" 23 seconds ago Up 22 seconds 8080/tcp infallible_fermat
查看所有容器(运行 停止)
docker ps -a
查看所有的容器id
docker ps -aq
如何运行一个容器
docker run 镜像名
或者docker run 镜像ID
$ docker run tomcat:8.0
简单运行tomcat镜像
docker run tomcat:8.0|(imageid)
运行tomcat容器,同时设置容器与宿主机端口的映射关系
P
docker run -p 8080(宿主机):8080 tomcat:8.0
$ docker run -p 8080:8080 tomcat:8.0
注意:可以映射多个端口
运行tomcat,开发端口映射,后台启动该服务
d
docker run -p 8082:8080 -d tomcat:8.0
$ docker run -p 8082:8080 -d tomcat:8.0
运行tomcat,开放端口映射,后台启动该服务,指定容器名称
-name
容器名称docker run -d -p 8083:8080 --name tomcat01 tomcat:8.0
$ docker run -d -p 8083:8080 --name tomcat01 tomcat:8.0
停止 重启 暂停 恢复容器
# 停止 $ docker stop 容器id|容器名称 #重启 $ docker restart 容器id|容器名称 #启动 $ docker start 容器id|容器名称 #暂停 $ docker pause 容器id|容器名称 #恢复 $ docker unpause 容器id|容器名称
docker中容器的基本操作2
杀死容器
docker kill id|name
$ docker kill id
删除容器
docker rm id|name
$ docker rm id
删除一个正在运行的容器
docker rm -f id|name
$docker rm -f id
查看容器内部的日志
docker logs id|name
$docker logs id
-t 加入时间戳
-f 跟随最新的日志打印 实时监控容器内服务的日志
--tail 数字显示最后多少条
进入容器的内部
容器内部其实是一个linux系统装上了相关的服务
进入容器内部相当于进入了一个新的linux系统里
docker exec -it id|name bash
# -it 表示交互模式
# 先查看一下运行的容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aaece9d9ef78 redis "docker-entrypoint.s…" 7 minutes ago Up 7 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp romantic_jepsen
$ docker exec -it aa bash # 这里的aa指的是aaece9d9ef78 可以缩写为aa
退出容器
exit
$ exit
容器与宿主机之间的文件拷贝
如何将容器中指定文件和目录拷贝到宿主机
docker cp 容器id|name:容器中文件或目录 主机目录
$ docker cp id:/home/index.html /root $ docker cp id:/usr/home/tt /root
如何将主机中指定文件和目录拷贝到容器内
docker cp 主机文件和目录 容器id:容器中目录
$ docker cp /root/index.html id:/home/
部署项目到docker容器内
- 将项目上传到linux服务器2. 通过
docker cp
命令将项目复制到tomcat的webapps目录中即可3. 使用ip+端口进行测试访问
docker cp /root/test.war id:/usr/lcoal/tomcat/webapp
docker中容器的基本操作3
查看容器内运行进程的指令
docker top 容器id或者 docker top 容器name
docker top id|name
查看容器内细节指令
docker inspect 容器id或者docker inspect 容器name
docker inspect id|name
容器数据卷机制【重点】
数据卷 Data Volume
作用:用来实现容器中的数据与宿主机中数据进行映射的(同步)
注意
:数据卷使用时必须在容器首次启动时设置使用:
docker run -v 宿主机目录:容器内目录
数据卷的真正意义
:在以后使用数据库搭建在容器中的时候,数据库用于存储,如果不使用数据卷的方式,会导致人员把搭建的mysql数据库的容器给删除了,就会导致数据丢失
使用数据卷将容器内数据映射到本地,把容器删除了也不会影响本机与数据卷同步的数据
创建方式一:使用绝对路径设置数据卷
$ docker run -v 宿主机绝对路径:容器内路径:(ro) # 注意:这种方式会将容器路径的原始内容全部清空,始终以宿主机路径为主 # ro: ready only 如果在设置数据卷时指定ro,代表以后容器内的路径是只读的 $ docker run -d -p 8081:8080 --name tomcat01 -v /root/apps:/usr/local/tomcat/webapps
创建方式二:使用别名方式设置数据卷
$ docker run -v aa:/usr/local/tomcat/webapps ...... # aa 代表docker数据卷中别名,注意:这个别名如果存在docker直接使用 aa不存在直接创建 # 使用别名方式保留容器路径内原始内容,前提别名对应不能存在内容 # 注意:docker根据别名创建目录默认在:/var/lib/docker/volumes/
docker中容器的基本操作4
docker三个核心概念
仓库 repostory
作用:docker 官方维护一个仓库,用来集中存储镜像
镜像 Image
作用:一个镜像代表一个软件服务
特点:只读
容器 container
作用:镜像没运行一次形成一个容器,运行的容器代表一个正在运行的软件服务
特点:可读可写
将容器打包成一个新的镜像
为什么要将容器打包程一个新的镜像?
原因:容器可读可写,基于这个特性我们可以对容器进行我们自己的深度定制
我们可以将修改的容器打包成一个新的镜像,以后基于这个镜像运行成容器存在原始定制特性
目的:可以将项目都放到原始容器后,在进行打包成新的容器,以后可放在多个新的服务器上,做到分布式部署
如何将容器打包成一个新的镜像
docker commit -m "描述信息" 容器id 镜像名:版本
或者docker commit -m "描述信息" 容器名称 镜像名:版本
$ docker commit -m "描述信息" id 镜像名称:版本
镜像的备份和恢复
备份镜像
docker save 镜像名:版本 -o 镜像原始名称-版本.tar
$ docker save tomcat:8.0 -o tomcat-8.0.tar # 默认备份到当前目录
恢复镜像
docker load -i 镜像原始名称-版本.tar
$ docker load -i tomcat-8.0.tar
docker中镜像原理
镜像为什么这么大?
原始 tomcat:10M 镜像 tomcat:356M
解释:容器独立操作系统(精简的linux操作系统+软件服务)====>镜像运行====>镜像(操作系统+软件服务)
镜像是一种轻量级的,可独立执行的软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的全部内容,包括代码,运行时所需要的库、环境变量和配置文件。
UniFS 联合文件系统 叠加文件系统
Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改为一次提交来一层一层的叠加,同时可以将不同目录挂在到同一个虚拟文件系统下。
Union文件系统是docker镜像的基础,这种文件系统特性就是一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
原理
docker中的镜像实际是由一层一层文件系统组成的,UnionFS联合文件系统
bootloader
引用加载器kwenel
内核- bootfs(bot file system)主要包含
bootloader
和kernel
,bootloader主要引导加载kernel,linux刚启动时会加载bootfs文件系统,在docker镜像的最底层就是botfs。这一层与Linux/Unix系统是一样的
,包括boot加载器(bootloader)和内核(kernel)。当boot加载完成之后,整个内核都在内存中,此时内存的使用权已经由bootfs交给内核,此时会卸载bootfs。 - rootfs(root file system)在bootfs之上,包含的就是典型的linux系统的
/dev
/proc
/bin
/etc
等标准目录和文件。rootfs就是各种功能不同操作系统的发行版本,比如ubuntu、centos
- 我们平时安装进虚拟机的centos都有几个GB,为什么docker这里才只有200MB?对于一个精简的os,rootfs可以很小,只需要包括最基本的命令,工具和程序库就可以了。因为底层直接使用
Host的Kernal
,自己只需要提供rootfs
就行了,由此可见不同的linux发行版,他们的bootfs一致,rootfs有区别。因此不通的发行版可以共用bootfs
。
- bootfs(bot file system)主要包含
为什么docker镜像要使用这种分层结构?
好处:资源共享
- 有多个镜像都是从相同的base镜像构建而来的,那么宿主机只需要在磁盘中保存一份base镜像。同时内存中也主需要加载一份base镜像,就可以为所有容器服务了,而且镜像的每一层都可以被共享。docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层被称为容器层,容器层之下都叫镜像层。
docker 安装mysql服务
建议:使用任何容器参考dockerhub官方网站+搜索引擎(百度google)
下载mysql镜像
- 访问docker hub 官方网站搜索mysql
- 确定版本 5.x (行业流行版本) 8.x(最新版本,引擎更快 特性)
# registry.hub.docker.com $ docker pull mysql:5.6
运行mysql
# 启动mysql 开放端口映射(3306) 指定root用户密码 -e代表环境 # 如果本机有mysql不能使用3306端口进行端口映射 $ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag $ docker yun -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.6
启动mysql 开放端口映射(3306) 指定root用户密码 -e MYSQL_ROOT_PASSWORD=xxx 后台运行 -d 指定名称 --name
# 后台启动 $ docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d --name mysql01 mysql:5.6
启动mysql 开放端口映射(3306) 指定root用户密码 -e MYSQL_ROOT_PASSWORD=xxx 后台运行 -d 指定名称 --name 总是运行 --restart=always
# 开机自启动 系统重启docker docker容器也跟着启动 #命令 `--restart=always` $ docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d --name mysql02 --restart=always mysql:5.6
启动mysql 开放端口映射(3306) 指定root用户密码 -e MYSQL_ROOT_PASSWORD=xxx 后台运行 -d 指定名称 --name 总是运行 --restart=always 数据卷持久化数据到宿主机
重要
推荐使用此方法
# 数据同步到宿主机 # -v 宿主机地址:容器地址 $ docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d --name mysql02 --restart=always -v /root/data:/var/lib/mysql mysql:5.6
docker 运行mysql容器数据备份
生产服务器:linux centos系统 【宿主机】
内部有:docker引擎
mysql容器在docker引擎之上
在使用mysql容器时数据卷虽然能备份数据
注意:数据卷将数据库底层文件系统进行备份
数据卷只能完成当前宿主机与数据库之间的数据存储,跨机器就实现不了。
不利于诗句迁移和备份,推荐使用sql文件形式去备份数据
如何在mysql中导出sql文件来备份文件
提示: |表示或者的意思,可以使用容器的id
方式一:利用mysql官方命令
mysqldump
完成信息的备份备份全部数据
$ mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD" > /root/all-databases.sql # mysql的命令 $ docker exec mysql|容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql # docker命令
备份指定库数据
$ docker exec mysql|容器id sh -c 'exec mysqldump -databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/xx-databases.sql #docker命令
备份指定库中的结构,不要数据
$ docker exec mysql|容器id sh -c 'exec mysqldump --no-data -databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/xx-databases.sql #docker命令
使用navicat提供数据备份进行备份
打开软件,连接数据库,找到数据表邮件选择转存储,仅结构
直接在对应库选择备份的表即可,导出即可。
docker安装redis服务
建议:使用任何容器参考dockerhub官方网站+搜索引擎(百度google)
redis支持内存数据持久化
aof持久化
redis服务器将所有redis客户端的写操作以命令方式记录到日志文件中aof更安全
rdb持久化
快照 redis服务器将某一时刻数据以快照文件形式写入到磁盘
下载redis
$ docker pull redis:5.0.12
运行redis
$ docker run -p 6379:6379 redis:5.0.12 # 后台运行 映射端口(6379) 后台启动 -d 指定名称 --name 总是启动 --restart=always $ docker run -d -p 6379:6379 --name redis01 --restart=always redis:5.0.12
docker 运行redis如何开启持久化
注意
只要开启了持久化,持久化文件生成在容器中的/data
目录中# 后台运行 映射端口(6379) 后台启动 -d 指定名称 --name 总是启动 --restart=always 开启持久化 --appendonly yes $ docker run -d -p 6379:6379 --name redis01 --restart=always --appendonly yes redis:5.0.12
docker 启动redis 开放端口 后台启动 指定名称 总是启动 开启持久化 映射数据文件外部
注意
使用此命令后!如果把redis容器删除了,也可以把数据恢复回来$ docker run --name redis03 -d -p 6379:6379 --restart=always -v /root/redisdata:/data redis-server --appendonly yes redis:5.0.12
docker 启动redis 使用配置文件启动
- 如何获取redis配置文件
- 第一种方式:下载对应版本找到配置文件,进行修改 使用完整配置文件启动
不推荐
- 第二种方式:创建指定的文件名称,直接书写修改属性即可
推荐
- 第一种方式:下载对应版本找到配置文件,进行修改 使用完整配置文件启动
- 上传配置文件到宿主机指定目录 /root/redisconf/redis.conf
- 数据卷挂载配置启动
$ docker run --name redis03 -d -p 6379:6379 --restart=always -v /root/redisconf:/data redis-server /data/redis.conf --appendonly yes redis:5.0.12
- 如何获取redis配置文件
docker 运行 nginx服务
注意 下载nginx时, 先确定下载版本, 按照docker pull nginx:版本号 去下载
下载 nginx
$ docker pull nginx
运行 nginx
# 启动nginx 映射端口(80) $ docker run -p 80:80 nginx # 启动nginx 映射端口(80) 后台启动 总是启动 指定名称 $ docker run -p 80:80 -d --restart=always --name nginx01 nginx:版本号 # 启动nginx 映射端口(80) 后台启动 总是启动 指定名称 加载指定nginx配置启动 -v 容器(/etc/nginx/nginx.conf) $ docker run -p 80:80 -d --restart=always --name nginx01 -v /root/nginxconf/nginx.conf:/etc/nginx/nginx.conf nginx:版本号
查看nginx容器是否启动成功
$ docker ps
实现反向代理 负载均衡
# 拷贝文件 $ docker cp 容器id:/etc/nginx/nginx.conf /root/nginxconf $ docker run -p 80:80 -d --restart=always --name nginx01 -v /root/nginxconf/nginx.conf:/etc/nginx/nginx.conf nginx:版本号
nginx作为服务器
$ docker run -p 80:80 -d --restart=always --name nginx01 -v /root/html :/usr/share/nginx/html nginx:版本号
nginx作为服务器 又想改配置
注意 -v 可以写多个,没有限制
$ docker run -p 80:80 -d --restart=always --name nginx01 -v /root/html :/usr/share/nginx/html -v /root/nginxconf/nginx.conf:/etc/nginx/nginx.conf nginx:版本号
docker中安装Elasticsearch服务
去docker hub确定版本
下载镜像
docker pull elasticsearch:6.8.10
运行es
# 启动 es 映射端口(9200(http) 9300(tcp)) $ docker run -p 9200:9200 -p 9300:9300 elasticsearch:6.8.10 # 启动 es 映射端口(9200(http) 9300(tcp)) 总是启动 指定名称 $ docker run -p 9200:9200 -p 9300:9300 elasticsearch:6.8.10 -d --restart=always --name=es elasticsearch:6.8.10 # 启动 es 映射端口(9200(http) 9300(tcp)) 总是启动 指定名称 通过数据卷映射数据到宿主机 容器内数据存储目录为(/usr/share/elasticsearch/data) $ docker run -p 9200:9200 -p 9300:9300 elasticsearch:6.8.10 -d --restart=always --name=es -v esdata:/usr/share/elasticsearch/data elasticsearch:6.8.10 # 注意:es启动如果没有知名单机方式启动,默认使用集群方式启动,如果使用集群方式启动在启动时会出现如下错误:1. max virtual menory areas vm.max_map_count[65530] is too low, increase to at least[262144] # 解决方案:在宿主机中执行如下操作 # 在centos虚拟机中,修改配置susctl.conf $ vim /etc/sysctl.conf # 加入如下配置 $ vm.max_map_count=262144 # 启动配置, 使配置生效 $ sysctl -p # 启动 es 映射端口(9200(http) 9300(tcp)) 总是启动 指定名称 通过数据卷映射数据到宿主机 通过数据将配置文件映射到宿主机 $ docker run -p 9200:9200 -p 9300:9300 elasticsearch:6.8.10 -d --restart=always --name=es -v esdata:/usr/share/elasticsearch/data -v /root/esconfig/elasticsearch.yml:/usr/share/elasticsearch/config/ elasticsearch:6.8.10
docker中安装MongoDB数据库
去docker hub确定版本
下载镜像
docker pull elasticsearch:6.8.10
运行MongoDB
# 运行
$ docker run -d -p 27017:27017 --name mymongo mongo:版本号
# 查看运行日志
$ docker logs -f mymongo
# 进入mongoldb容器
$ docker exec -it mymongo bash
# 常见具有权限的容器
$ docker run --name mymongo -p 27017:27017 -d mongo --auth
# 进入容器配置用户名和密码
$ mongo
$ use admin #选择admin库
$ db.createUser({user:'root',pwd:'root',roles:[{role:'root',db:'admin'}]}) # 创建用户,此用户创建成功,则后续操作都需要用户认证
$ exit
# 将mongodb数据目录映射到宿主机中
$ docker run -d -p 27017:27017 -v /root/mongo/data:/data/db --name mymongo mongo
docker中容器之间的通信 -网络使用
容器间通信
说明: 容器之间通过网络相互通信
官方说明:
当docker启动的时候,会自动在主机上创建一个docker0的虚拟网桥,实际上是linux的一个bridge,可以理解为一个软件交换机,它会在挂在到它的网口之间进行转发。
同时,docker随机分配一个本地未占用的私有网段(在RFC1918中定义)中的一个地址给
docker0
接口,比如典型的172.17.42.1
,掩码为255.255.0.0
。伺候启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址。当创建一个docker容器的时候,同时会创建一个
veth pair
接口(当数据包发送到一个接口时,另外一个接口也可以受到相同的数据包)。这对接口一端在容器内,即etho
;另一端在本地并被挂在到docker0
网桥,名称以veth
开头(例如:vethAQI2QT
)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信,docker就可以创建在主机和所有容器之间的一个虚拟的共享网络。网络总结
- 默认docker在创建容器时,将所有的容器都连接到docker0网桥上。默认在docker0网桥的容器都可以使用容器内ip地址进行通信。
- 默认docker在创建容器时,将所有容器都连接到docker0网桥上,默认在docker0网桥的容器都可以使用容器名字进行通信
自定义网桥实现网桥中一组容器的通信
缺点:没有办法跨桥通信
docker中网桥类型
NETWORK ID NAME DRIVER SCOPE af94280cb29a bridge bridge local 6762fc67bdec host host local 2f9d4d1e4b61 none null local
docker中网络类型:bridge、host、null
创建网络自定义网桥
$ docker network --help # 查看network帮助 $ docker network create -d bridge 网络名 # 创建(默认) 网络名称 $ docker network ls # 查看网络 $ docker network inspect 网络名 # 查看某一个网络细节 $ docker network rm 网络名 # 删除某一个网络 $ docker network prune # 删除所有未被使用的网络名
运行多个容器在指定网络中
启动容器时明确指定容器使用哪个网络
$ docker run -d --network 网络名称
启动容器之后容器加入某个网络中
$ docker run -d -p 8080:8080 --name tomcat01 --network ems tomcat:8.0 $ docker run 0d -p 8081:8080 --name tomcat01 --network ems tomcat:8.0 $ docker network inspect ems # 查看ems网络下的容器
docker高级数据卷
高级数据卷配置
定义:用来实现宿主机和容器之间文件目录映射同步
数据卷使用 -v 宿主机路径:容器内路径
注意:必须在容器首次启动时指定
使用绝对路径数据卷
$ docker run -v /root/datas:/usr/local/tomcat/webapps :tomcat:8.0
使用别名方式数据卷
$ docker run -v bb:/usr/local/tomcat/webapps :tomcat:8.0
别名到底是什么
别名代表一个docker自身维护数据卷
查看所有docker维护数据卷
docker volume ls
查看数据卷详细内容
docker insepct 数据卷别名、网桥名称、容器名称 docker network inspect 查看网桥详细 docker volume inspect 查看数据卷详细
删除一个数据卷
docker volume rm 数据卷别名
创建一个别名数据卷
docker volume create 数据卷别名
Dockerfile 重点
什么是Dockerfile
Dockerfile可以认为是docker镜像的描述文件,是由一系列命令和参数构建成的脚本,主要作用是用来构建docker镜像的构建文件。
作用
通过Dockerfile文件构建一个属于自己的镜像
为什么要使用Dockerfile构建镜像的?
官方的镜像确实足够号了,足够适用于大多数应用程序,但是如果我们想自助机属于我们自己的业务镜像,这个时候必须自定义镜像。
如何使用Dockerfile构建自己的镜像
在指定位置创建一个Dockerfile文件
编写dockerfile相关语法
通过dockerfile构建镜像
$ docker build -t aa:1.0 .... 指定dockerfile文件所在位置
Dockerfile构建镜像流程
要求: Dockerfile一行只能写一条指令
Dockerfile内容基础知识
1. 每条保留字指定都必须为大写,且后面都要跟至少一个参数。
2. 指领按照从上到下,顺序执行。
3. # 表示注释
4.每条指令都会创建一个新的镜像层,并对镜像进行提交。
Dockerfile的保留命令
保留字 | 作用 |
---|---|
FORM | 当前镜像基于哪个镜像 第一个指令必须是FORM |
MAINTAINER | 镜像维护者的姓名和邮箱地址 |
RUN | 构建镜像时需要运行的指令 |
EXPOSE | 当前容器对外暴露出的端口号 |
WORKDIR | 指定在创建容器后,终端默认登录进来的工作目录,一个落脚点 |
ENV | 用来在构建过程中设置环境变量 |
ADD | 将宿主机目录下的文件拷贝进镜像,且ADD命令会自动处理URL和解压tar包 |
COPY | 类似于ADD,拷贝文件和目录到镜像中,将从构建上下文目录中<原路径>的文件/目录赋值到新的一层镜像内<目标路径>位置。 |
VOLUME | 容器数据卷,用于数据保存和持久化工作 |
CMD | Dockerfile中可以有多个CMD命令,但只有最后一个有效,CMD会被docker run之后的参数替换。 |
ENTRYPOINT | 指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样。都是在指定容器启动程序及其参数 |
使用Dockerfile
在宿主机的某一个文件夹里创建一个名称为Dockerfile的文件
使用编辑器工具或者vim去编写Dockerfile文件里内容
小技巧:运行centos容器,直接进入到centos系统中
docker run -it centos:latest
$ mkidr docker $ cd docker $ touch Dockerfile
Dockerfile文件内容
FORM centos:latest RUN
FORM命令
基于那个镜像进行构建新的镜像,在构建时会自动从docker hub拉取base镜像,必须作为Dockfile的第一个指令出现
语法
FORM <image> FORM <image>[:<tag>] # 使用版本不写为latest FORM <image>[@<digest>] # 使用摘要
MAINTAINER命令
镜像维护者的姓名和邮箱地址[废弃]
语法
MAINTAINER <name>
RUN命令
RUN命令将在当前映像之上的新层中执行任何命令并提交结果,生成的提交映像将用于Dockerfile中的下一步。
语法
RUN<command> # RUN yum install vim
EXPOSE命令
EXPOSE命令 仅仅使声明当前容器中服务端口是谁
语法
EXPOSE 8808
WORKDIR命令
用不为DOCKERfile中任何RUN、CMD、EXPOSE、ADD指令设置工作目录。如果WORKDIR不存在,即使它没有在任何后续Dockfile指令中使用,它也将被创建。
语法
WORKDIR /path/to/workdir 指定原始镜像存在目录, 不存在目录 WORKDIR /a WORKDIR b WORKDIR c 注意:WORKDIR指令可以在Dockerfile中多次使用,如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对
ENV命令
用来构建镜像设置环境变量,这个值将出现在构建阶段中所有的后续指令的环境中
语法
ENV <KEY> <VALUE> ENV <KEY> = <VALUE> # 声明变量 ENV A = /home # 如何使用变量 WORKDIR $ A
ADD命令
用来从context上下文复制新文件、目录或远程文件url,并将他们添加到位于指定路径的映像文件系统中。
语法
ADD home* /mydir/ 通配符添加多个文件 ADD hom?.txt /mydir/ 通配符添加 ADD test.txt relativeDir/ 可以指定相对路径
CMD &ENTRYPINT作用
作用:都是用来指定容器启动时默认执行指令
注意:CMD指令可以存在多个,但是存在多个只有最后一个生效
使用语法
CMD &ENTRYPOINT
直接命令方式
java -jar ems.jar
json 数组方式
["java", "-jar", "ems.jar"]
Docker自定义项目镜像
- 创建项目
- 开发项目功能,连接配置数据库,代码生成
- 测试项目代码
- 打包项目
- 编写Dockerfile生成项目【核心步骤】
- 运行镜像
现有docker进行项目部署存在问题
一个项目会存在多个容器, 但是每个容器之间存在着启动的依赖关系。
为了完成一个完整的项目势必用到N个容器配合完成项目中业务开发。
容器的编排至关重要
现在这种方式使用容器,没有办法站在项目的角度将一个项目用到一组容器划分到一起,日后难点在于项目多服务器部署
项目角度管理项目用到一组容器
Docker Compose
作用:给容器进行编排,针对多个容器进行编排,单个容器不需要使用它。
简介
compose
项目时Docker官方的开源项目,负责实现对Docker容器集群的快速编排,从功能上看,跟Openstack
中的Heat
十分类似。其代码目前在https://github.com/docker/compose上开源。
compose
定位是【定义和运行多个Docker容器的应用】其前身是开源项目FIG。通过介绍,我们知道使用一个
Dockerfile
模板文件,可以让用户很方便的定义一个单独的应用容器,然而在日常工作中,经常会配到需要多个容器相互配合来完成某项任务的情况。例如:要实现一个web项目,除了web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
compose
刚好满足这样的需求,它允许用户通过一个单独的docker-compose.yml
模板文件来定义一组相关联的应用容器为一个项目。compose
中有两个重要的概念- 服务:一个应用容器,实际上可以包括若干运行相同镜像的容器实例。
- 项目:由一组关联的应用容器组成一个完整业务单元,在
docker-compose.yml
文件中定义。
compose
的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷的生命周期管理。compose
项目有Python编写,实现上调佣了docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持docker api 就可以在其上利用compose
来进行编排管理。安装与卸载
在线安装
从官方github release处直接下载编译好的二进制文件即可,
在linux64位系统中直接下载对应的二进制包
$ sudo curl -L <https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname> -s`-`uname -m` > /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose
离线安装
# 下载 docker-compose 脚本 # 放入/usr/local/bin # sudo chmod +x /usr/local/bin/docker-compose
docker-compose第一案例
创建第一个项目 mkdir ems
在ems目录创建一个docker-compose.yml模板文件
编辑docker-compose.yml模板文件
启动一个容器写法
version:"3.8" # docker-compose版本和docker 的版本关系,必须对应 services: tomcat: image: tomcat:8.0 # 代表使用哪个镜像,类似于docker run的镜像名称 ports: -8080:8080 # 代表宿主机和容器中端口映射,类似于docker run -p参数 多个参数往下增加
启动多个容器写法
tomcat和tomcat01是两个不同的容器
version:"3.8" services: tomcat: container_name: tomcat01 # 代表给容器指定一个名称 类似与docker run --name 参数 推荐使用默认名称 不推荐填写这个配置项 image: tomcat:8.0 # 代表使用哪个镜像, 类似于 docker run 指定的镜像名称 ports: # 代表宿主机和容器中端口映射,类似于docker run -p参数 - 8080:8080 tomcat01: image: tomcat:8.0 ports: - 8081:8081 redis: image: redis:5.0.12 ports: - "6379:6379" mysql: image: mysql:5.6 ports: - "3306:3306" environment: # 代表给当前容器启动指定环境,类似于docker run -e MYSQL_ROOT_PASSWORD=ROOT - "MYSQL_ROOT_PASSWORD=root" volumes: # 代表给当前容器和宿主机指定数据卷,类似于 docker run -v 用于数据持久化存储 注意:docker-compose使用绝对路径必须要有文件夹存在,如果不存在要先创建才能使用。 - /root/mysqldata1:/var/lib/mysql - mysqlData: /var/lib/mysql # 也可以使用别名方式, 但要使用mysqlData必须要声明数据卷,下面就是声明 mysqlData volumes: mysqlData: # 声明mysqlData给上面使用, 创建的时候会给加上项目名_mysqlData
启动docker-compose一组服务
$ docker-compose up # 执行运行 $ docker-compose down # 清除缓存
docker-compose 支持的全部命令
# 网址: <https://yeasy.gitbook.io/docker_practice/install>
build指令
构建
docker build -t centos7. dockerfile
作用:通过docker-compose 在启动容器之前根据dockerfile构建镜像
使用方法
version: "3.8" # 管理一组服务 services: tomcat: image: tomcat:8.0 ports: -"8080:8080" apps: build: ./ # 指定Dockerfile上下文目录【要求项目和docker-compose.yml和Dockerfile文件要在一起】 它会先找当前目录下的Dockerfile文件里的配置文荣执行完成,在执行docker-compose.yml context: ./ # 用来指定Dockerfile上下文目录 dockerfile: Dockerfile # 指定Dockerfile文件名称 ports: - "8081:8081"
Command指令
作用:覆盖容器启动后默认执行的命令
使用方法
version: "3.8" # 管理一组服务 services: tomcat: image: tomcat:8.0 ports: -"8080:8080" apps: build: ./ # 指定Dockerfile上下文目录【要求项目和docker-compose.yml和Dockerfile文件要在一起】 它会先找当前目录下的Dockerfile文件里的配置文荣执行完成,在执行docker-compose.yml context: ./ # 用来指定Dockerfile上下文目录 dockerfile: Dockerfile # 指定Dockerfile文件名称 ports: - "8081:8081" command:["ls"] # 用来覆盖容器启动后默认指令, 类似于docker image run
container_name指令
作用:用来指定docker-compose启动容器名称 【不推荐指定容器名称】
depends_on指令
作用:解决容器的依赖、启动先后的问题
使用方法
version: "3.8" # 管理一组服务 services: tomcat: image: tomcat:8.0 ports: -"8080:8080" apps: build: ./ # 指定Dockerfile上下文目录【要求项目和docker-compose.yml和Dockerfile文件要在一起】 它会先找当前目录下的Dockerfile文件里的配置文荣执行完成,在执行docker-compose.yml context: ./ # 用来指定Dockerfile上下文目录 dockerfile: Dockerfile # 指定Dockerfile文件名称 ports: - "8081:8081" command:["ls"] # 用来覆盖容器启动后默认指令, 类似于docker run image 覆盖的命令 depends_on: -tomcat # 书写依赖的服务 -mysql -redis
environment指令
作用: 用来给容器启动指定环境变量 相当于docker run -e 选项
env指令
作用:用来给容器启动 指定启动文件, 文件里的内容是容器启动时需要使用的指令
像mysql 的MYSQL_ROOT_PASSWORD: root 指令可以写到指定的配置文件里
使用方法
version: "3.8" # 管理一组服务 services: tomcat: image: tomcat:8.0 ports: -"8080:8080" apps: build: ./ # 指定Dockerfile上下文目录【要求项目和docker-compose.yml和Dockerfile文件要在一起】 它会先找当前目录下的Dockerfile文件里的配置文荣执行完成,在执行docker-compose.yml context: ./ # 用来指定Dockerfile上下文目录 dockerfile: Dockerfile # 指定Dockerfile文件名称 ports: - "8081:8081" command:["ls"] # 用来覆盖容器启动后默认指令, 类似于docker run image 覆盖的命令 depends_on: -tomcat # 书写依赖的服务 -mysql -redis mysql: image: mysql:5.6 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root env_file: - ./aa.env
expose指令
作用: 用来指定构建惊喜哪个过程中容器暴露的端口号
使用方法
version: "3.8" # 管理一组服务 services: tomcat: image: tomcat:8.0 ports: -"8080:8080" apps: build: ./ # 指定Dockerfile上下文目录【要求项目和docker-compose.yml和Dockerfile文件要在一起】 它会先找当前目录下的Dockerfile文件里的配置文荣执行完成,在执行docker-compose.yml context: ./ # 用来指定Dockerfile上下文目录 dockerfile: Dockerfile # 指定Dockerfile文件名称 ports: - "8081:8081" command:["ls"] # 用来覆盖容器启动后默认指令, 类似于docker run image 覆盖的命令 depends_on: -tomcat # 书写依赖的服务 -mysql -redis mysql: image: mysql:5.6 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root env_file: - ./aa.env expore: "8080:8080"
image指令
作用:用来指定启动容器使用镜像是谁,相当于 docker run image(镜像名)
label指令
作用: 用来添加元信息,给人看的信息
networks指令
作用: 用来指定容器所使用的网桥是什么,需要配合声明使用
使用方法
# 指定使用网桥 networks: -dangdang # 声明网桥名称为dangdang networks: dangdang:
ports指令
作用: 用来指定宿主机和容器的映射端口 相当于docker run -p
使用方法
ports: -"3300" -"8080:8080" -"49100:22" -"127.0.0.1:8001:8001"
volumes指令
作用: 用来指定容器中目录和宿主机目录的映射 相当于docker run -v
使用方法
# 使用数据卷 volumes: -mysqlData:/var/lib/mysql # 声明别名数据卷 volumes: mysqlData:
restart指令
作用: 用来指定docker容器(服务)总是运行 docker run --restart=always
docker-compose 相关指令
docker-compose 命令 项目|项目中某个服务,注意:没有特殊说明时,默认都是对项目操作
语法:
docker-compose -f docker-compose.yml 命令 【选项】【服务id】
up [重点]
$ docker-compose up # 对整个项目操作 $ docker-compose up 服务id # 对当前docker-compose中对应服务id容器操作
- 该命令十分强大,它将尝试自动完成包括构建镜像,重新创建服务,启动服务,并关联服务相关容器的一系列操作。
- 链接的服务都将会被自动启动,除非已经处于运行状态。
- 大部分的时候都可以直接通过该命令来启动一个项目。
- 默认情况下,
docker-compose up
启动的容器都在前台,控制台将会同时打印所有容器的数据信息,可以很方便进行调试。 - 当通过
ctrl+c
停止命令时,所有容器将会停止。 - 如果使用
docker-compose up -d
,将会在后台启动并运行所有的容器,一般推荐生产环境下使用该选项。 - 默认情况下,如果服务容器已经存在,
docker-compose up
将会尝试停止容器,然后重新创建(保持使用volumes-from挂载的卷),以保证新启动的服务匹配docker-compose.yml
文件的最新内容。
down[重点]
注意:
docker-compose down 关闭所有容器
此命令将会停止
up
命令所启动的容器,并移除网络$ docker-compose down # 对整个项目操作 $ docker-compose down 服务id # 对服务id操作有效 并移除网络
exec
$ docker-compose exec 服务id bash # 进入容器
ps
$ docker-compose ps # 展示所有运行的服务 $ docker-compose ps -q
restart
$ docker-compose restart # 项目服务重启 $ docker-compose restart 服务id # 对指定项目服务重启 $ docker-compose restart -t 20s 服务id # 在指定时间对指定项目服务重启【20秒之后重启服务】
rm
$ docker-compose rm # 删除整个项目 $ docker-compose rm 服务id # 删除指定项目服务 # -f $ docker-compose rm -f 服务id # 强制删除 #-v [谨慎使用] $ docker-compose rm -v 服务id # 删除,会把项目的数据卷删除
top
$ docker-compose top # 查看整个项目中所有服务容器内运行进程 $ docker-compose top 服务id # 查看某个服务的运行进程
unpause
$ docker-compose unpause # 恢复处于暂停状态的服务 $ docker-compose unpause 服务id # 恢复某个服务
pause
$ docker-compose pause # 暂停所有服务 $ docker-compose pause 服务id # 暂停某个服务
logs
$ docker-compose logs # 查看整个项目日志 $ docker-compose logs 服务id # 查看某个服务的日志 # -f 实时 $ docker-compose -f #实时查看整个项目日志 $docker-compose -f 服务id #实时查看某个服务日志
Docker可视化界面工具
第三方公司开源portainer项目,用来对docker引擎中运行所有容器进行可视化的展示
使用
安装Portainer
$ docker pull portainer/portainer $ docker volume create portainer_data $ docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer $ docker ps
浏览器登录
<https://localhost:9000>
Docker报错
- 第一种报错
[root@VM-16-11-centos ~]# docker run -p 6379:6379 redis
docker: Error response from daemon: driver failed programming external connectivity on endpoint awesome_kare (a692caa9c368942329b345dd4aff29e89cb76644e0298847008c26c1c5af3f68): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 6379 -j DNAT --to-destination 172.17.0.2:6379 ! -i docker0: iptables: No chain/target/match by that name.
原因:
# docker容器底层原理:在启动docker的时候会自动在iptables中注册一个链,通过防火墙的链也可以找到其注册的信息,主要注册这些链,是docker的容器为了暴露端口而使用的。
# 具体原因是:删除了iptables中的链
# 删除连接的方式有很多种
# 重启firewalld防火墙即可对其清除,firewalld是centos7以上,iptables是centos6以下都会有,而firewalld的底层是涉及在iptables上的,在启动firewalld的时候会自动删除iptables链的相关链接
# 删除该链接的其他方式博主暂未遇到有特殊情况的,待发现
# 所以在涉及防火墙firewalld的命令或者是iptables中的命令的时候
# 小心删除其涉及docker的链
解决方法:
# 重启防火墙,
$ systemctl restart firewalld
# 重启docker
$ systemctl restart docker
# 查询docker的链
$ iptables -L
- 第二种报错
$ docker run -it centos
# 执行上面的命令进入到了docker centos容器系统里
# 进入到centos 在执行下面命令时报错
$ yum update
# 报错
Failed to set locale, defaulting to C.UTF-8
CentOS Linux 8 - AppStream 11 B/s | 38 B 00:03
Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist
解决方案
$ cd /etc/yum.repos.d
$ mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
curl -o /etc/yum.repos.d/CentOS-Base.repo <https://mirrors.aliyun.com/repo/Centos-8.repo>