目录
Docker简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。
Docker为什么会出现
在孵化一个新的产品的时候,我们至少要部署两套环境,即测试环境和生产环境。
比如我们的系统中引入了诸如Redis、ElasticSearch、RocketMQ等中间件技术,我们的工作可能不仅仅是开发代码逻辑。
可能还需要搭建这些组件需要运行的环境,如下载安装包、安装、配置等等;并且在部署的过程中还会部署错导致组件无法启动成功,从而浪费大量的时间。
比如我们做一次系统迭代升级,我们希望只关注程序(jar)本身,并不想去关注开发环境相关的问题;Docker的出现就是解决诸如此类的问题。
Docker是如何解决的
简单的理解就是基于镜像去做的,它的思想有点类似于手机软件的应用市场。我们平时想要用一个软件只需要从应用市场下载安装即用,Docker也是类似的
apk-----发布应用市场---------下载apk安装使用
jar-------打包并且带上环境发布------Docker仓库--------下载镜像即可使用
Docker安装
这个不在赘述,官网上很详细 https://docs.docker.com/get-docker/
Docker常用命令
命令相关官方文档 https://docs.docker.com/engine/reference/commandline/docker/
帮助命令
docker version --查看docker版本,这个命令能执行成功表示安装成功
docker info --更加详细的信息
docker --help --如果不知道命令可以显示相关命令
镜像命令
镜像命令
docker images --查看本地所有的镜像
常用的可选项:
-a, --all Show all images (default hides intermediate images)
-q, --quiet Only show image IDs
docker search '要搜索的镜像名' --搜索镜像
比如搜索mysql 就是 docker search mysql
常用的可选项:
-f, --filter filter Filter output based on conditions provided
docker pull 镜像名[:tag] --下载镜像,如果不写tag默认就是latest最新的版本
#docker pull mysql --下载mysql最新镜像
#docker pull mysql:5.7 --下载mysql5.7版本镜像
docker rmi 镜像id --删除镜像
docker rmi 镜像id1 镜像id2 镜像id3 --删除多个镜像
docker rmi $(docker images -aq) --删除全部镜像
docker commit -a "作者" -m "提交信息" 容器id 提交的镜像名 : [TAG ] --提交一个镜像
容器命令
docker run 可选参数 镜像名 --运行一个镜像容器
docker ps --列出所有运行中的容器
常用可选项:
-a 列出当前运行的容器并显示历史运行过的容器
-q 只显示容器的编号id
exit --直接停止并退出容器
Ctrl (Mac就是Command) + p + q --容器不停止退出
docker rm 容器id --删除指定容器
docker rm $(docker ps -aq) --删除所有容器
docker ps -as |XARGS docker rm --删除所有的容器
docker start 容器id --启动容器
docker -d run 镜像名 --后台启动容器
docker stop 容器id --停止容器
docker restart 容器id --重新启动容器
docker kill 容器id --强制停止容器
#常见的坑:docker使用后台启动容器必须有前台应用否则会自动停止,现象就是 docker -d run 启动一个容器 然后 docker ps 发现没有容器运行
docker logs -tf --tail 容器id --查看容器日志
docker inspect 容器id --查看容器的元数据
docker exec -it 容器id --进入容器
docker cp 容器id:文件路径 宿主机器路径 --将容器id下面的文件拷贝到宿主主机上
Docker部署Nginx-简单Demo
部署过程
#1.搜索镜像 docker search nginx --filter=stars=5000
#2.拉取镜像 docker pull nginx:1.14
#3.查看镜像是否拉取成功 docker images -a
#4.后台运行容器 docker run -d --name nginx01 -p 8080:80 nginx:1.14
#4.1 -p 绑定外部端口8080(Nginx默认端口是80)
#4.2 --name 去一个别名
#4.3 -d 后台运行容器
部署成功后访问本机的8080端口,访问正常
外部请求到容器服务大致流程
进入启动好的Nginx容器
#进入容器docker exec -it nginx01(获取容器id) /bin/bash
#查看nginx配置 cat /etc/nginx/conf.d/default.conf
Docker部署tomcat-Demo
部署过程
#查找镜像 docker search tomcat --filter=stars=3000
#拉取镜像 docker pull tomcat
#查看镜像是否拉取成功 docker images -a
#启动tomcat容器 docker run -d --name=tomcat01 -p=8081:8080 tomcat
#进入容器查看tomcat启动日志
#1. docker exec -it tomcat01(或者容器id) /bin/bash
#2. cat /usr/local/tomcat# cat /usr/local/tomcat/logs/catalina.对应日期.log
#看一下容器是否启动成功 docker ps
访问tomcat
#原因是webapps目录下无任何文件,相关文件在webapps.disk目录下 拷贝过来即可
#在/usr/local/tomcat目录下 cp -r webapps.disk/* webapps
#再次访问即可
进阶部署ElasticSearch+Kibana
有挑战的点:
- Es暴露给外部端口比较多
- Es的数据的安全性可靠行要保证不能容器没了数据也没了
- Es非常的消耗内存
部署过程与坑
#镜像仓库搜索es docker search elasticsearch
#拉取es镜像 docker pull elasticsearch
#启动elasticsearch docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms=512m -Xmx=512m"
--这里的-p可以绑定多个端口;-e指定运行参数
--es默认2g(5.0以上版本),而在创建docker时默认内存是1g,导致启动失败,这时就需要修改加参数修改容器内存:所加参数为 :-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
--或者修改docker默认内存
访问es
Docker镜像原理
大概原理
https://blog.youkuaiyun.com/songcf_faith/article/details/82787946 --这里有相关详细介绍
有这么一个场景,我在Linux服务器上搭建了java运行环境,然后又搭建了mysql环境,用来部署我的服务A。下一次我想在另一台机器上部署类似的服务B的时候,我只想直接启动服务并不想重复这个搭建运行的环境的流程,UnionFS就派上用场了。
UnionFS(联合文件系统)是Docker镜像的基础,镜像可以通过分层来继承,基于基础镜像可以制作各种具体的应用镜像。
Docker镜像就是由一层一层的文件系统组成。
bootfs(boot file system)主要包含bootloader和内核,bootloader主要引导加载内核,Linux刚启动的时候会加载bootfs,在Dokcer最底层其实是bootfs。这一层与Linux/Unix系统一样的,当boot加载完后整个内核就都在内存中了,这个时候内存的使用权已经由bootfs转移给了内核此时系统也会卸载bootfs。
rootfs(root file system),在bootfs之上,比如Linux系统中的/dev /proc /bin /etc等标准文件,rootfs操作系统的发型版本,比如centos、ubuntu等。
所以对于一个精简的OS,rootfs可以很小,只需要最基本的命令即可,底层的话还是用的本机的内核,自己只需要提供rootfs即可,Docker即是这样做的。
#我们可以通过dokcer image inspect 镜像名来看下docker的分层
#以nginx为例子, docker image inspect nginx:1.14
验证Docker镜像分层的概念
我们知道镜Docker镜像都是只读的。
比如我现在对这个nginx的原始镜像添加了一个文件,再重新commit成一个新的镜像nginx:01;其实就是在基础层上面再搭建了一层,如下图所示。
运行命令看下镜像的元数据 ,重点是看它的分层 docker image inspect nginx:1.14
运行同样的命令看下我提交的这个nginx镜像的元数据 docker image inspect nginx:01
可以发现这时候有四层,并且前面三层是一样的、复用的;验证了docker分层。
Dokcer精髓之容器数据卷
为什么要有容器数据卷?
痛点:如果我们在容器中启动了mysql,过了一段时间不小心将这个mysql容器删除了,那么我们的数据也会随之被删除。
所以我们需要有一个容器与本机数据共享的技术来解决这个问题。
大致原理
本质上是通过目录的挂载,将容器内的目录挂载到服务器的文件系统中,形成一个双向的绑定,不管操作容器内或者主机对应的目录,两边都会一起更改。
使用容器数据卷方式
#通过docker run 附加参数-v来挂载
-- docker run -it -v 主机目录:容器内目录 镜像名
#测试 docker run -d -p 8888:80 -v ~/opensource/ceshi:/home nginx:1.14
--将本机的~/opensource/ceshi目录和容器的/home目录绑定到一起
#使用命令进入容器 docker exec -it 容器id /bin/bash
--进入容器的/home创建test.txt,查看本机的~/opensource/ceshi目录下会不会也有test.txt
测试文件同步
#使用 docker inspect 容器id 也能看到容器元数据下的挂载数据描述
#停止容器 docker stop 容器id
--看到主机的test.txt文件依旧存在,绑定后反向操作也是成立的 本机->容器
测试容器mysql数据
#启动mysql容器 -d后台运行 -p端口映射 -v卷挂载 -e环境配置 --name 容器名
#docker run -d -p 3388:3306 -v ~/opensource/test/conf:/etc/mysql/conf.d -v ~/opensource/test/data:/var/lib//mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5
#连接本地mysql创建test库后进入本机的目录下看是否有对应的库数据
具名挂载与匿名挂载
#匿名挂载 -v 直接加容器内路径
docker run -d -v /etc/nginx nginx:1.14
#查看所有的volume
docker volume ls
----------------------------------------
#具名挂载 -v 卷名:容器内路径
#查看挂载在本机的具体目录 docker volume inspect 卷名
----------------------------------------
#还有一种就是上面用的指定路径的挂载. ro -> read only rw->read write
docker run -d -v 本机路径:容器路径(:ro 或者 rw) 镜像名:[tag]
数据卷容器-容器间数据同步
#通过 --volumes-from实现容器间的数据同步
#父子容器共享的文件,如果父容器被停止或删除都不会影响子容器,共享的文件并不会随之被删除
docker run -d -it --name [容器名] --volumes-from [父容器名] [镜像名字]
---------------这个技术可以用在本机多个mysql容器共享数据------------------------
DockerFile
DockerFile概念
DockerFile就是用来构建docker镜像的构建文件,也就是一串命令脚本;每一个脚本就相当于对应镜像的一层。
简单的DockerFile构建
#每个指令必须是大写、命令从上往下执行、#表示注释、每一个命令都会创建一个新的镜像层
#构建步骤:
1.编写一个DockerFile文件
2.docker build 构建镜像
3.docker run 启动容器
4.docker push 发布镜像(Dockerhub、阿里云镜像仓库)
# DokcerFile里面命令全都是大写并且严格区分大小写
-----DockerFile文件内容-------------
FROM centos
VOLUME ["myDir1"] --匿名挂载
CMD echo "ok"
-----------------------------------
#通过dokcer build -f dockerFile文件名 -t 镜像名:[tag] .
------------------最后面小数点符号不能去掉-----------------------
当我们使用 docker build 命令来构建镜像时,这个构建过程其实是在 Docker引擎 中完成的,而不是在本机环境。
那么如果在 Dockerfile 中使用了一些 COPY 等指令来操作文件,如何让 Docker引擎 获取到这些文件呢?
这里就有了一个 镜像构建上下文 的概念,当构建的时候,由用户指定构建镜像的上下文路径,而 docker build 会将这个路径下所有的文件都打包上传给 Docker 引擎,引擎内将这些内容展开后,就能获取到所有指定上下文中的文件了。
比如说 dockerfile 中的 COPY ./package.json /project,其实拷贝的并不是本机目录下的 package.json 文件,而是 docker引擎 中展开的构建上下文中的文件,所以如果拷贝的文件超出了构建上下文的范围,Docker引擎 是找不到那些文件的。
------------------最后面小数点符号不能去掉-----------------------
DockerFile的指令
FROM #基础镜像是哪个,构建的基础
MAINTAINER #镜像谁维护的 一般名字+邮箱
RUN #镜像构建的时候需要运行的命令
ADD #需要添加的内容Copy文件,如果是个压缩文件(tar.gz、zip) Dokcer会自动解压
WORKDIR #镜像的工作目录
VOLUME #容器挂载的目录
EXPOSE #对外暴露的端口 可选项-p是一个道理
CMD #指定容器运行的时候要运行的命令(这个多个只有最后一个会生效,替换)
ENTYPOINT #指定容器运行的时候要运行的命令 (追加命令 )
COPY #类似ADD指令,就是将文件拷贝到镜像中
ENV #构建的时候设置的环境变量
DockerFile小Demo
centos命令增强的镜像
#1.编写DockerFile文件(centos增强)
-----------文件内容------------
FROM centos
MAINTAINER lee
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo "ok"
CMD /bin/bash
-----------文件内容------------
#2.构建镜像 这里后面的'.'小数点不能去掉(前面有解释)
docker file -f [dockerFile的name] -t [镜像名:tag] .
自己搭建的tomcat镜像
#1.编写DockerFile文件(从0搭建tomact)
-----------文件内容------------
FROM centos
MAINTAINER lee
ADD jdk-8u212-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.46.tar.gz /usr/local
ENV JAVA_HOME=/usr/local/jdk1.8.0_212
ENV CLASSPATH=$JAVA_HOME/lib/rt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
RUN yum -y install vim
ENV WORKPATH=/usr/local
WORKDIR $WORKPATH
EXPOSE 8080
CMD echo "ok"
CMD /usr/local/apache-tomcat-9.0.46/bin/startup.sh && tail -f usr/local/apache-tomcat-9.0.46/logs/catalina.out
-----------文件内容------------
#2.构建镜像 这里后面的'.'小数点不能去掉(前面有解释)
docker file -f [dockerFile的name] -t [镜像名:tag] .
发布自己搭建的tomcat镜像到阿里云
1. 登录阿里云Docker Registry
$ sudo docker login --username=我是嘉伟baba registry.cn-hangzhou.aliyuncs.com
用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
您可以在访问凭证页面修改凭证密码。
2. 从Registry中拉取镜像
$ sudo docker pull registry.cn-hangzhou.aliyuncs.com/dockerrpo/01:[镜像版本号]
3. 将镜像推送到Registry
$ sudo docker login --username=我是嘉伟baba registry.cn-hangzhou.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/dockerrpo/01:[镜像版本号]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/dockerrpo/01:[镜像版本号]
请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。
4. 选择合适的镜像仓库地址
从ECS推送镜像时,可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。
如果您使用的机器位于VPC网络,请使用 registry-vpc.cn-hangzhou.aliyuncs.com 作为Registry的域名登录。
5. 示例
使用"docker tag"命令重命名镜像,并将它通过专有网络地址推送至Registry。
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
registry.aliyuncs.com/acs/agent 0.7-dfb6816 37bb9c63c8b2 7 days ago 37.89 MB
$ sudo docker tag 37bb9c63c8b2 registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816
使用 "docker push" 命令将该镜像推送至远程。
$ sudo docker push registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816
Docker网络