1 介绍
Docker 是一个开源的应用容器引擎,基于Go 语言并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
docker官网:https://www.docker.com/
文档:https://docs.docker.com/
仓库:https://hub.docker.com/
2 为什么出现
一款软件产品: 开发–上线 两套环境,应用环境,应用配置。
开发–运维出现问题:在我的电脑上可以允许,发布上线就出现问题。
环境配置是十分的麻烦,每一个及其都要部署环境(集群Redis、ES、Hadoop…) ,费事费力。
发布一个项目( jar + (Redis MySQL JDK ES) ),项目能不能带上环境安装打包。
开发环境Windows—发布到Linux:
传统:开发jar,运维来发布
现在:开发打包部署上线,一套流程做完!
安卓流程:java — apk —发布(应用商店)一 张三使用apk一安装即可用!
docker流程: java-jar(环境) — 打包项目帯上环境(镜像) — ( Docker仓库:商店)
3 虚拟机和容器化技术
虚拟机技术缺点: 1、资源占用十分多 2、冗余步骤多 3、启动很慢!
容器化技术不是模拟一个完整的操作系统
虚拟机技术的不同: 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响
DevOps(开发、运维)
(1)应用更快速的交付和部署
传统:一对帮助文档,安装程序。
Docker:打包镜像发布测试一键运行。
(2)更便捷的升级和扩缩容
使用了 Docker之后,部署应用就和搭积木一样,项目打包为一个镜像,扩展服务器A,服务器B
(3)更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的
(4)更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多的容器实例,服务器的性能可以被压榨到极致。
docker 组成
(1)镜像(image):
docker镜像就好比是一个目标,可以通过这个目标来创建容器服务,tomcat镜像==>run==>容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
(2)容器(container):
Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。Docker容器包含了所有的某个应用运行所需要的环境。目前就可以把这个容器理解为就是一个简易的服务器系统。
(3)仓库(repository):
仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库。(很类似git)
安装
Linux安装(win安装直接去官网下载安装包 Docker Desktop)
#1.卸载旧版本
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
#2.需要的安装包
yum install -y yum-utils
#3.设置镜像的仓库
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
#上述方法默认是从国外的,不推荐
#推荐使用国内阿里云的
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#3.更新yum软件包索引,这里有时会出现版本问题,centos8没有该参数,解决办法为:去掉fast参数,
yum makecache fast
#5.安装yum源中默认的Docker
yum -y install docker(这命令安装的是老版本,拉镜像的时候会出现missing signature key)
#安装新版本Docker,推荐
yum -y install docker-ce
#5.启动docker
systemctl start docker #运行Docker守护进程
systemctl stop docker #停止Docker守护进程
systemctl restart docker #重启Docker守护进程
systemctl enable docker #设置Docker开机自启动
systemctl status docker #查看Docker的运行状态
#6. 使用docker version查看是否按照成功
docker version
#1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2. 删除资源
rm -rf /var/lib/docker
# /var/lib/docker 是docker的默认工作路径!
4 Docker的常用命令
4.1 帮助命令
docker version #显示docker的版本信息。
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令
4.2 image
docker images 查看本地镜像列表
docker image ls 查看本地镜像列表
docker search [image name] 查询仓库中的镜像
docker pull [image name] 从仓库中获取镜像
docker rmi [image name]或者[image id] 从仓库中获取镜像
docker rmi -f $(docker images -aq) 删除全部镜像
4.3 container
docker run [image name] 新建并启动容器
docker ps 查看运行中的容器
docker ps -a 查看所有本地容器
docker container ls 查看运行中的容器
docker container ls --all 查看所有本地容器
docker rm [container id] 移除一个已停止的容器
docker rm -f [container id] 移除一个运行中的容器
docker rm -f $(docker ps -aq) 删除所有的容器
docker start [container id/name] 启动容器
docker restart [container id/name] 重启容器
docker stop [container id/name] 停止当前正在运行的容器
docker kill [container id/name] 强制停止当前容器
docker run [可选参数] image | docker container run [可选参数] image
#参书说明
--name="Name" #容器名字 tomcat01 tomcat02 用来区分容器
-d #后台方式运行
-it #使用交互方式运行,进入容器查看内容
-p #指定容器的端口 -p 8080(宿主机):8080(容器)
-P(大写) #随机指定端口
#进入当前正在运行的容器
docker exec -it 容器id/容器名字 bashshell 进入当前容器后开启一个新的终端,可以在里面操作
docker attach 容器id 进入容器正在执行的终端
运行mysql
//首先要创建挂载的目录
mkdir -p /data/mysql
//切换到对应的目录
cd /data/mysql
//使用$PWD,要先切换到对应的目录
docker run -p 3306:3306 --name mysql -v $PWD/conf:/etc/mysql/conf.d
-v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -e TZ=Asia/Shanghai -d mysql:5.7
//window版本,最新版本8.0映射出来的端口连接不上,所以要指定5.7版本
docker run -p 3307:3306 --name mysql
-v C:/development/docker_container/mysql/conf:/etc/mysql/conf.d
-v C:/development/docker_container/mysql/logs:/logs
-v C:/development/docker_container/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
参数讲解: -p 是将docker中mysql端口号3306映射成为3306端口,也可以选择不映射,使用默认的3306
--name mysql 运行服务的取名
-v 是将主机目录下的文件挂载到容器中路径下(/scy是我本人用户)
-e MYSQL_ROOT_PASSWORD 初始化root用户密码
-e TZ=Asia/Shanghai 时区修改为中国时区,docker安装得msyql时区有问题
-d mysql -d 后台运行mysql,可以指定版本
//进入mysql容器
docker exec -it mysql /bin/bash
//然后连接上mysql后输入账号
mysql -u root -p;
1、#Docker mysql 出现 sql_mode=only_full_group_by问题
#进入绑定mysql容器/etc/mysql/conf.d 对应的/data/mysql/conf目录下
创建mysqld.cnf文件并增加
[mysqld]
#sqlmode
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
然后查看是否还存在only_full_group_by
select @@sql_mode;
select @@global.sql_mode;
2、如需修改数据库max_connections=10000,wait_timeout=600和interactive_timeout=800,先进入容器,修改/etc/mysql/mysql.conf.d/mysqld.cnf文件
docker exec -it mysql /bin/bash
进入/etc/mysql/mysql.conf.d
cd /etc/mysql/mysql.conf.d
安装vim
apt-get update
apt-get install vim
然后再修改mysqld.cnf,添加以上三个参数
vim mysqld.cnf
最后重启容器
docker restart mysql
运行redis
//首先要创建挂载的目录
mkdir -p /data/redis
//切换到对应的目录
cd /data/redis
//当指定配置文件启动redis时,需先在$PWD/conf/redis.conf下面把redis.conf配置创建好
//不然默认加载的redis.conf是一个空目录,redis.conf可以在网上找到
docker run -p 6379:6379 --name redis -v $PWD/conf/redis.conf:/etc/redis/redis.conf
-v $PWD/data:/data -d redis redis-server /etc/redis/redis.conf
--appendonly yes --requirepass 123456
//window版本
docker run -p 6379:6379 --name redis
-v C:/development/docker_container/redis/conf/redis.conf:/etc/redis/redis.conf
-v C:/development/docker_container/redis/data:/data
-d redis redis-server /etc/redis/redis.conf --appendonly yes --requirepass 123456
//进入redis容器
docker exec -it redis redis-cli
//或者
docker exec -it redis /bin/bash
//在输入
redis-cli
//创建redis.conf文件,添加以下内容
port 6379
timeout 0
databases 8
save 900 1000
save 600 10000
save 300 100000
save 60 1000000
dbfilename dump.rdb
appendonly yes
appendfilename appendonly.aof
maxmemory 0
maxclients 65535
requirepass 123456
4.4 查看日志
docker logs --help
#显示日志
docker logs -t --tail n 容器 id/name 查看n行日志
docker logs -ft 容器 id/name 跟着日志
docker top 容器 id/name 查看容器中进程信息ps
docker inspect 容器 id/name 查看镜像的元数据
4.5 其他
#将运行的镜像内容修改,提交进行修改后的镜像保存。
docker commit -a "作者" -m "提交记录注释" 容器id 自定义镜像名称
#将镜像保存为压缩包
docker save -o abcde.tar 镜像名称
#加载镜像
docker load -i abcde.tar
#从容器内拷贝到主机上
docker cp 容器id:容器内路径 主机目的路径
docker cp 56a5583b25b4:/hello.java /home
5 容器数据卷
将应用和环境打包成一个镜像, 如果数据都在容器中,那么我们容器删除,数据就会丢失,这样就需要将数据可以持久化本地磁盘。
容器之间可以有一个数据共享的技术。Docker容器中产生的数据,同步到本地,这就是卷技术。目录的挂载,将我们容器内的目录,挂载到Linux上面。
总结:容器的持久化和同步操作,容器间也是可以数据共享的。
使用命令挂载 -v
-v, --volume list Bind mount a volume
docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口
# /home/ceshi:主机home目录下的ceshi文件夹 映射:centos容器中的/home
docker run -it -v /home/ceshi:/home centos /bin/bash
#这时候主机的/home/ceshi文件夹就和容器的/home文件夹关联了,二者可以实现文件或数据同步了
#通过 docker inspect 容器 id/name 查看
docker inspect 6064c490c371
#win10下docker运行mysql
docker run -p 3307:3306 --name mysql
-v C:/development/docker_container/mysql/conf:/etc/mysql/conf.d
-v C:/development/docker_container/mysql/logs:/logs
-v C:/development/docker_container/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
验证:停止容器,宿主机修改文件,启动容器,容器内的数据依旧是同步的。
结论:以后修改只需要在本地修改即可,容器内会自动同步。
# 三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的
# 查看所有的volume(卷)的情况
$docker volume ls
DRIVER VOLUME NAME
local 21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0 #匿名
local juming-nginx #具名
# 通过 -v 卷名:查看容器内路径
# 查看一下这个卷
$ docker volume inspect juming-nginx
[
{
"CreatedAt": "2020-05-23T13:55:34+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", #默认目录
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
# 通过 -v 容器内路径: ro rw 改变读写权限
#ro #readonly 只读
#rw #readwrite 可读可写
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作
所有的docker容器内的卷,没有指定目录的情况下都是在**/var/lib/docker/volumes/自定义的卷名/_data**下,
如果指定了目录,docker volume ls 是查看不到的。
多个MySQL同步数据
命名的容器挂载数据卷
$ docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
#让mysql02 继承 mysql01
$ docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候,可以实现两个容器数据同步!
结论:容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的。
6 Dockerfile
Dockerfile就是用来构建docker镜像的构建文件,命令脚本。通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层。
Dockerfile是面向开发的,以后发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单。Docker镜像逐渐成企业交付的标准,必须要掌握。
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行产品。
Docker容器:容器就是镜像运行起来提供服务
构建步骤:
(1)编写一个dockerfile文件
dockerfile是用来构建docker镜像的文件,命令参数脚本。
DockerFile的指令
FROM # from:基础镜像,一切从这里开始构建
MAINTAINER # maintainer:镜像是谁写的, 姓名+邮箱
RUN # run:镜像构建的时候需要运行的命令
ADD # add:步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
WORKDIR # workdir:镜像的工作目录
VOLUME # volume:挂载的目录
EXPOSE # expose:保留端口配置
CMD # cmd:指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # entrypoint:指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # onbuild:当构建一个被继承DockerFile这个时候就会运行onbuild的指令,触发指令
COPY # copy:类似ADD,将我们文件拷贝到镜像中
ENV # env:构建的时候设置环境变量!
Tomcat镜像:
准备tomcat 和 jdk 到当前目录,编写好README
$ vim dockerfile
FROM centos # 基础镜像centos
MAINTAINER czq<12345678@qq.com> # 作者
COPY README /usr/local/README # 复制README文件
ADD jdk-8u231-linux-x64.tar.gz /usr/local/ # 添加jdk,ADD 命令会自动解压
ADD apache-tomcat-9.0.35.tar.gz /usr/local/ # 添加tomcat,ADD 命令会自动解压
RUN yum -y install vim # 安装 vim 命令
ENV MYPATH /usr/local # 环境变量设置 工作目录
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_231 # 环境变量: JAVA_HOME环境变量
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 # 环境变量: tomcat环境变量
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35
# 设置环境变量 分隔符是:
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# 设置暴露的端口
EXPOSE 8080
# 设置默认命令
CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out
(2)docker build 构建称为一个镜像
# 因为dockerfile命名使用默认命名 因此不用使用-f 指定文件
$ docker build -t mytomcat:0.1 .
(3)docker run运行镜像
# -d:后台运行 -p:暴露端口 --name:别名 -v:绑定路径
$ docker run -d -p 8080:8080 --name tomcat01
-v /home/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test
-v /home/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs mytomcat:0.1
$ docker exec -it 自定义容器的id/name /bin/bash
$ cul localhost:8080
由于做了卷挂载,直接在本地编写项目就可以发布了
(4)docker push发布镜像(DockerHub 、阿里云仓库)
发布到 Docker Hub:Docker Hub
$ docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
$ docker login -u 你的用户名 -p 你的密码
提交 push镜像
# 会发现push不上去,因为如果没有前缀的话默认是push到 官方的library
# 解决方法:
# 第一种 build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了
$ docker build -t kuangshen/mytomcat:0.1 .
# 第二种 使用docker tag #然后再次push
$ docker tag 容器id kuangshen/mytomcat:1.0
#然后再次push
$ docker push kuangshen/mytomcat:1.0
发布到 阿里云镜像服务上:阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台
$ sudo docker login --username=zchengx registry.cn-shenzhen.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像版本号]
# 修改id 和 版本
sudo docker tag a5ef1f32aaae registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:1.0
# 修改版本
$ sudo docker push registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像版本号]
7 Docker 网络
8 SpringBoot微服务打包Docker镜像
(1)构建SpringBoot项目
(2)打包运行
mvn package
(3)编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
(4)构建镜像
# 1.复制jar和DockerFIle到服务器
# 2.构建镜像
$ docker build -t xxxxx:xx .
(5)发布运行
以后我们使用了Docker之后,给别人交付就是一个镜像即可。