一,docker的用途:
提供统一的环境:在本地测试其他人软件,或者把软件和环境一起打包,给其他人进行测试
提供快速拓展,弹性伸缩的云服务:比如双十一时候业务量会比平时多好几倍,为了应对提前扩容是个好办法,但是平时又不需要用到,就会造成浪费,一种方法是可以节前把机器运过来,拓展,开机,过了大型活动后下线,这种就比较麻烦。用了docker后,可以只进行简单配置,10台服务器可以变成上千台,节日时就能快速进行拓展,后续又快速的把能力进行转移下线,节省资源。有了标准化程序之后,不管在什么机器上,直接把它下载过来并启动,而无需担心有什么问题。
防止其他用户的进程把服务器资源占用过多。使用docker可以把不同内容进行隔离,对方发生的错误只会在固定范围内产生影响,不会对其他模块产生牵连
二,docker的好处:
1)可以使开发完全控制环境,之前这些操作是依赖运维的,现在就不需要依赖他们,更加灵活,也降低了风险。
左侧是构建出来的镜像,会被推到镜像仓库,然后测试人员会对镜像进行测试,包括集成测试,容量测试,预发测试等,这些环境未来使用的也是同一个镜像,这样我们可靠性就大大增加,维护环境的精力也大大减少。
2)部署简单,减轻运维工作量
3)节省机器资源
三,docker特点:
-
标准化
1)运输方式(只需要通过命令即可把程序和环境从一个机器运到另一个机器上)
2)存储方式(程序和环境的存储,不需要关心程序存在什么地方,只需要关心使用或停止它的时候执行对应的命令即可)
3)API接口(不需要tomcat,rabbitmq等应用等自己的命令了,使用同样命令即可控制所有应用)
灵活:即使是最复杂的应用也可以集装箱化
轻量级:容器利用并共享主机内核
便携式:可以在本地构建,部署到云,并在任何地方运行
四,docker的组成
1,image镜像:
本质就是文件,包括应用程序文件,运行环境等
存储:联合文件系统,UnionFS,是分层文件系统,把不同文件目录挂到一个虚拟的文件系统下,具体分几层可以自己控制。每一层构建好后,下一层不再变化,上面一层是以下面一层作为基础的,最终多层组成了文件系统。
2,容器:
1,镜像类似于java中的类,而容器就是示例,镜像运行后就变成一个容器
2,容器的这一层是可以修改的,而镜像是不可以修改的(跑起来之后上面就会多一层可修改的层,主要修改工作都放在这一层)
上面的图只有第一层是可写的,因为需要创建日志啥的,程序运行时如果要写镜像文件,可以写在这一层。其他都是只读的。比如我修改了一个系统文件,这个文件属于apache这层的,这样可能就产生2个文件。处理方式是在找这个文件的时候,会从上往下开始找,如果上面没有才会找到下面这层。由于我们已经修改了上层的apache文件,而且原来文件是只读的,不可写,所以修改实际意味着把文件复制一份,然后放到最上层中,这样会在最上层中有一个变化的副本,未来想找文件时候,就可以一下子找到这个变化过的文件,修改也就生效的。
3,同一个镜像可以生成多个容器独立运行,而他们之间没有任何的干扰。
3,仓库:
1)相当于一个中转站,类似百度网盘,把文件上传上去,如果要使用就自己去下载
2)地址:
国外:hub.docker.com
3)也分为公有和私有
可以自己搭建一个镜像中心
4,client和deamon
client:客户端,提供给用户一个终端,用户输入docker提供的命令来管理本地或远程的服务器
deamon:服务端守护进程,接收client发送的命令并执行相应的操作
五,常用命令
ps:docker命令是区分大小写的!
命令 | 作用 |
---|---|
systemctl start docker | 启动docker |
systemctl enable docker | 设置开机自启动 |
docker version | 查看docker版本 |
docker info | 查看具体信息 |
docker images | 查看镜像 |
docker search busybox | 搜索镜像 |
docker pull xx | 拉取镜像(默认下载最新版本,也可以加上版本号下载指定版本,推荐这种) |
docker run xx | 运行镜像 |
docker save busybox > busybox.tar | 导出 |
docker load < busybox.tar | 导入 |
docker rmi busybox:latest | 删除 |
docker tag busybox:latest busybox:test | 更改镜像名 |
docker history busybox | 查看镜像创建历史 |
docker ps 或者docker ps -a | 查看当前容器列表 |
docker run -d --name busybox busybox:latest ping 114.114.114.114 | 让docker容器在后台运行 (-d 后台运行) |
docker stats busybox | 查看资源占用 |
docker start/restart/stop/kill busybox | 启动/重启/停止运行/杀掉容器 |
docker pause/unpause busybox | 暂停容器 |
docker rm -f busybox | 强制删除容器(正在运行的程序可以使用这个命令强制删除) |
docker stop+容器名 | 停止容器运行 |
docker exec -it [OPTIONS] CONTAINER COMMAND [ARG...] | 访问容器内部 exec:执行一个命令, it:把容器内部终端映射到当前终端 |
docker cp busybox:/etc/hosts hosts | 复制文件 |
docker logs -f busybox | 查看容器日志 |
docker inspect 容器id | 查看容器/镜像的元信息 |
docker inspect -f '{{.Id}}' 容器id | 格式化输出(提取内容里的id) |
docker diff busybox | 查看容器内的文件结构 |
配置docker加速器
新建配置文件:vim daemon.json
{
"registry-mirrors": ["https://mqxz7mjm.mirror.aliyuncs.com"]
}
配置完以后记得重启!!
systemctl docker restart
其他镜像可以参考:https://www.runoob.com/docker/docker-mirror-acceleration.html
六,docker的网络模式(主要是前面2种)
bridge :桥接:仿佛是docker容器和外面的宿主机搭建了一座桥,可以通过这座桥使两端进行通信,当然内部外部还是完全独立的。(90%以上使用这个)
host:主机:容器不会获得独立网络,而是和我们主机使用同一个网络,容器不会虚拟出自己的网卡ip等,会直接使用宿主机上的ip和端口
-
none:没有网络
docker的隔离性是它的一大特点,它的网络也是隔离的,意味着里面运行的网络,外面是运行不到的。如果想对里面网络进行感知,需要用到网络配置,配置好之后可以让他们进行映射,
实操:
访问docker内的nginx,重点就是端口映射
docker run -d -p 8080:80 本机的8080端口映射到容器内部的80端口(-d:在后台启动)
配置完后记得去阿里云的安全组规则进行配置,否则无法生效通过端口映射方法可以在一台服务器上去布置很多docker,每个docker是独立的并且可以通过一个端口来实现和外界的映射关系,实现了隔离和资源分配的目的。我们可以把ngnix换成任何我们想要的服务器,tomcat,springboot程序等。
如果一个容器对外暴露的端口很多,一个个写笔记繁琐,有个更方便的方法。
docker run -d -P xxx :创建容器并随机生成不同端口
-P:自动分配端口号,并把内部容器所有端口都进行映射
-p:手动指定端口映射关系
七,使用dockerfile生成docker
dockerfile:文本文件,用来配置镜像用的
我们往往是在已有镜像上添砖加瓦,形成自己的镜像(一个镜像往往是通过继承另一个镜像得来的)
-
使用dockerfile的好处:
1)把文件放在版本控制下,这样我们对环境做的修改可以被追踪到。
2)有了这个文档后,可以清楚知道程序运行所需的环境,软件,配置等。
3)保证文档是最新的,新来的小伙伴可以很方便的知道具体的环境配置
关键字 | 作用 |
---|---|
FROM | 基础镜像,FROM命令必须是dockerfile的首个命令 |
LABEL | 为镜像生成元数据标签信息,比如软件版本,作者信息之类的 |
USER | 指定运行容器时的用户名或UID,后续RUN也会使用指定用户,默认是管理员用户 |
RUN | RUN命令是dockerfile命令的核心部分,它接受命令作为参数并用于创建镜像。每条RUN 命令在当前基础镜像上执行,并且会提交一个新的镜像层 |
WORKERDIR | 设置CMD指明的命令的运行目录,为后续的RUN,CMD,ENTRYPOINT,ADD指令配置工作目录 |
ENV | 容器启动的环境变量,比如软件版本之类的 |
ARG | 构建环境的环境变量,针对dockerfile |
COPY | 复制文件,比如当前目录有很多配置文件需要复制到容器里,就可以使用 |
CMD | 容器运行时执行的默认命令,有个缺陷:使用docker run去执行容器的时候,如果后面加上一些别的指令,CMD里面的指令会被覆盖掉 |
ENTRYPOINT | 指定容器的入口,使用docker run去执行容器的时候,如果加上 --entrypoint参数,指令不会被覆盖掉 |
HEALTHCHECK | 容器健康状态检查, |
示例:使用dockerfile构建nginx容器,添加容器健康检查
1,新建一个dockerfile
# 基于 nginx:1.17.9镜像构建
FROM nginx:1.17.9
# 指定信息
LABEL maintainer="234333@qq.com"
# 设置环境变量
ENV NGINX_VERSION 1.17.9
ARG work_pwd=/data/html/
# 切换 root 用户
USER root
# 执行命令,安装curl 软件,设置软连接把nginx服务的日志显示
RUN apt-get -yq update && apt-get install -y curl && \
ln -sf /dev/stdout /var/log/nginx/access.log && \
ln -sf /dev/stderr /var/log/nginx/error.log
# 挂载类
VOLUME ["/data"]
# 设置工作目录
WORKDIR $work_pwd
# 复制index.html 文件到WORKDIR目录下
COPY index.html .
# 映射 80 端口
EXPOSE 80
# 此处CMD 作为 ENTRYPOINT 的参数
CMD ["nginx","-g","daemon off;"]
STOPSIGNAL SIGRTMAX
# 检查容器健康,通过访问NGINX服务80端口,来判断容器服务是否健康
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
2,构建镜像
# -t:指定一个tag,这里指定标签为n,1表示版本号。后面那个“.”表示在当前目录下进行构建的
docker build -t n:1 .
成功后如图所示
执行成功后可以搜到这个
我们可以运行它
八,docker里配置nginx
- 下载nginx安装包
docker pull nginx:1.17.9
- 运行
docker run -p 80:80 nginx:1.17.9
浏览器输入ip地址即可实现访问
配置后台运行
docker run -d --name docker -p 80:80 nginx:1.17.9
九,docker部署testlink
1,创建docker网络
docker network create testlink
2,安装数据库
docker run -d --name mariadb -e MARIADB_ROOT_PASSWORD=mariadb -e MARIADB_USER=bn_testlink -e MARIADB_PASSWORD=bn_testlink -e MARIADB_DATABASE=bitnami_testlink --net testlink -v ${PWD}/mariadb:/bitnami bitnami/mariadb:10.3.22
3,运行testlink(docker -p 宿主机端口号:容器端口号)
docker run -d -p 8023:8080 -p 443:8443 --name testlink -e TESTLINK_DATABASE_USER=bn_testlink -e TESTLINK_DATABASE_PASSWORD=bn_testlink -e TESTLINK_DATABASE_NAME=bitnami_testlink --net testlink -v /testlink:/bitnami bitnami/testlink:1.9.20
十,docker部署Jenkins
1,拉取镜像
docker pull jenkins/jenkins:lts
2,创建docker的文件映射卷
docker volume create jenkins
3,创建实例
# 8080端口:Jenkins对外服务端口
# 50000端口:Jenkins的slaver连接主服务器时候使用
docker run -d --name=jenkins -p 8080:8080 -p 50000:50000 -v jenkins:/var/jenkins_home jenkins/jenkins:lts
查看日志:这步可以获取密码,当然也可以用下面的查看的方式找到密码
# 容器id:之前启动成功时候那一长串号码
docker logs -f 容器id
4,获取初识密码
docker exec -it cat /var/jenkins_home/secrets/initialAdminPassword
5,打开浏览器,输入网址(ip:端口号)把密码输入进去
6,手动部署
- 简易部署:java -jar jenkins.war(不推荐)
- 正式部署:
1)调参:调增jvm参数
2)应用容器:使用tomcat,jetty启动
3)反向代理:使用nginx设置域名,https
二,Jenkins配置
修改时区:
删除已有实例
docker rm -f jenkins
重新创建实例并设置时区
docker run -d --name jenkins -p 8080:8080 -p 50000:50000 \
-v jenkins:/var/jenkins_home \
-e JAVA_OPTS=-Duser.timezone=Asia/Shanghai \
jenkins/jenkins:lts
十一,docker-compose简介
docker-compose是用于定义和运行多容器的docker应用程序的工具,通过docker compose,可以使用yaml文件来配置应用程序的服务
compose的使用一般分为三步:
1,使用dockerfile定义应用程序的环境,以便可以在任何地方复制它
2,在docker-compose.yml中定义组成应用程序的服务,以便他们可以在隔离环境中一起运行
3,运行 docker-compose up,然后compose启动并运行您的整个应用程序
十一,docker的registry
- registry是docker官方用来托管私有镜像的仓库。
- 运行pull,push,search时,是通过docker daemon 与docker registry通信。有时候使用docker hub这样的公共仓库可能不方便,我们可以通过registry创建一个本地仓库
- 因为docker服务器在国外,我们下载东西会比较慢,我们可以通过把镜像下载到本地,然后放在registry里面,本地局域网其他服务器都可以通过访问这个registry去下载之前下载过的镜像,提高下载速度,或者是存放公司通过dockerfile构建的镜像。
1,运行registry
docker run -d -p 5000:5000 -v ${PWD}/registry:/var/lib/registry --restart always --name registry registry:2.7.1
2,访问:http://ip:端口号/v2/_catalog 验证是否成功
ps:里面没有内容是因为没有上传镜像
3,进入另一个服务器,编辑daemon.json文件,把里面配置的内容改为之前配置的服务器的ip地址+端口号并保存,如下:
{
"insecure-registries": ["192.168.0.101:5000"]
}
4,重启服务,让服务生效
systemctl restart docker
目前是没有任何镜像的
5,切回本地搭建registry服务的终端,下载一个镜像,并使用docker tag命令给镜像打个标签
docker tag nginx:1.18.0 192.168.0.101:5000/nginx:1.18.0
6,推到本地仓库
docker push 192.168.0.101:5000/nginx:1.18.0
7,切换另一台要下载东西的服务器,下载刚刚推到registry的nginx
docker pull 192.168.0.101:5000/nginx:1.18.0
这个时候查看之前打开的网址,会看到nginx在上面了
十二,docker镜像构建
在日常工作中,常常需要制作自己项目的镜像,一般通过以下2种方式制作:docker commit ,dockerfile。
1.docker commit 一般是从一个运行状态的容器来创建一个新的镜像。定制镜像应该使用dockerfile来完成。默认commit镜像,对外不可解释,不方便排查问题,可维护性差。
2,docker commit 容器名 新镜像名:tag 只推荐临时使用。
docker commit nginx n:2
3,dockerfile文件还需要通过docker build 进行构建
4,docker build配置:
参数 | 作用 |
---|---|
.dockerignore | 忽略文件 |
docker build -f | 指定文件 |
docker build -t | 添加标签 |
docker build --no-cache | 不使用缓存 |
docker build --build-arg | 构建时变量 |
ARG指令变量
十三、docker与虚拟机的区别
- 容器与容器之间只是进程的隔离,而虚拟机是完全的自愿隔离
- 虚拟机的启动可能需要几分钟,docker的启动是秒级甚至更短
- 容器使用宿主操作系统的内核,而虚拟机使用完全独立的内核