**本人博客网站 **IT小神 www.itxiaoshen.com
Docker文档官网
Docker是一个用于开发、发布和运行应用程序的开放平台。Docker使您能够将应用程序与基础设施分离开来,以便快速交付软件。使用Docker,您可以以与管理应用程序相同的方式管理基础设施。通过利用Docker快速发布、测试和部署代码的方法,您可以显著减少编写代码和在生产环境中运行代码之间的延迟。
简单的说就是我们开发软件是需要部署还包括基础环境如mysql、redis、jdk和基础数据等,且还需重复部署很多台服务器,部署环境又有开发环境、测试环境、预生产环境、正式线上环境等,从开发-测试-运维都是很费力费时,特别是由于环境依赖等问题有时需要耗费较大时间解决,有了docker可以把上面问题解决,docker图标上面就有集装箱图标,这个比喻很恰当,docker将所有内容存在集装箱内,搬运至任何地方;而docker的核心思想也就是打包装箱,每个箱子之间互相隔离,而docker也是利用隔离机制将服务器利用到极致。
在DevOps时代可以更快的交付和部署,docker容器是直接运行在宿主机上,没有自己的内核和硬件,所以运行很轻便,每个容器间是互相隔离的,都有自己文件系统不影响;docker可以打包镜像发布实现一键运行,使用docker我们可以像搭积木一样增加一层层镜像实现,docker是内核级别的虚拟化,比虚拟机更少的抽象层,一台物理机上可以运行很多的容器示例,可以把服务器性能压榨到极致。
2010年,几个大胡子年轻人在旧金山成立了一家做 PaaS 平台的公司,起名为dotCloud,专注于LXC容器化技术,docker刚诞生没有引起行业的主体,刚开始发展不太如意。2013年10月 dotCloud 公司更名为 Docker 股份有限公司,2014年8月 Docker 宣布把平台即服务的业务「dotCloud」出售给位于德国柏林的平台即服务提供商「cloudControl」,dotCloud 的历史告一段落
2013年docker开源,越来越多人发现docker这个宝藏,与虚拟机技术vmware相比,vmware镜像经常是几个G,启动要几分钟,而docker非常轻巧,docker直接运行镜像就可以了,秒级启动服务,太厉害了
Docker使用客户-服务器架构。Docker客户端与Docker守护进程对话,后者负责构建、运行和分发Docker容器。Docker客户端和守护进程可以运行在同一个系统上,或者您可以将一个Docker客户端连接到一个远程Docker守护进程。Docker客户端和守护进程使用REST API通过UNIX套接字或网络接口进行通信。另一个Docker客户端是Docker Compose,它允许您使用由一组容器组成的应用程序。
简单理解,docker宿主机是docker核心引擎,用于下载镜像和运行容器,镜像就好比我们Java中的类,而容器就是类New出来的对象;docker registry如docker hub 就好比maven中央仓库,用于存放制作好的docker镜像,也支持本地私有部署如docker harbor,可以通过docker push或docker pull 进行上传或下载镜像;而docker client就是我们操作docker宿主机的一个命令行工具
Docker是用Go编程语言编写的,并利用了Linux内核的若干特性来交付其功能。Docker使用名为名称空间的技术来提供名为容器的独立工作区。当您运行一个容器时,Docker会为该容器创建一组名称空间。这些名称空间提供了一个隔离层。容器的每个方面都运行在一个单独的名称空间中,它的访问仅限于该名称空间。
[docker安装官网地址](https://docs.docker.com/engine/install/centos/)
详细参考官网,官网有非常详细安装说明
#如果安装过docker删除已安装docker版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine sudo yum install -y yum-utils sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo #安装最新版本的docker核心引擎、命令行客户端、容器 sudo yum install docker-ce docker-ce-cli containerd.io #如果要安装特定版本的Docker引擎,请在repo中列出可用的版本,然后选择并安装 yum list docker-ce --showduplicates | sort -r sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io #启动docker sudo systemctl start docker #运行hello-world容器 sudo docker run hello-world
安装完毕后检查下版本和测试hello-world如有如下显示就可以尽情使用单机版的docker了,注意这个只是单机的玩具,如果想要在单机编排运行容器得使用docker-compose,如果要用到docker集群得使用docker swarm。
所以我们再安装docker-compose,docker-compose安装非常简单,直接将docker-compose可行性文件拷贝到系统的/usr/local/bin,然后通过sudo chmod +x /usr/local/bin/docker-compose赋予执行文件权限即可,docker-compose可执行文件可到docker的GitHub去获取;我的虚拟机是CentOS Linux release 8.3.2011,所以我们选择这里选择Docker for Linux安装,
配置阿里云镜像
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://f9dk003m.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
docker官方文档
docker verison docker info docker --help
docker images --all , -a 显示所有镜像 --digests 显示摘要 --filter , -f 条件过滤输出 --format 使用Go模板打印漂亮的图像 --no-trunc 不截断输出 --quiet , -q 只显示图像id
docker search mysql --no-trunc //查找镜像
docker pull tomcat //拉取镜像,如果不写tag就是默认latest即最新版本,比如要指定安装mysql5.7则在后面直接:5.7即可,下面有很多Pull complete则代表的是一层层的镜像进行分层下载,这个也是docker image的核心,属于联合文件系统
docker run --name nginx-test -p 8080:80 -d nginx //运行容器,如果本地没有image镜像文件则会先执行pull拉取镜像,--name为容器名字用于区分容器,-p有几种写法,这里是一种,前面的对外暴露8080端口,外部要访问容器80端口则是通过宿主机的8080端口映射实现,映射容器内部端口80,nginx默认配置端口为80, -d后台运行;其他还有很多参数如-it使用交互式方式运行,进入容器查看内容,--rm是停止容器后直接删除容器数据
我的docker宿主机为192.168.3.117 访问8080
docker ps //查看运行容器 加-a则查询全部容器 docker images //显示全部镜像 docker push //上传镜像,上传镜像需要先执行登录 docker login //docker仓库地址 -u 用户名 -p 密码,退出 docker login out //退出登录 docker create //创建一个新的容器,和run的差别就是不启动容器 docker start //启动容器编号或名称 docker stop //停止容器编号或名称 docker restart //重启容器编号或名称 docker kill //杀掉编号的容器 docker pause //暂停容器 docker unpause //取消暂停容器 docker rm //删除容器编号或名称,不能删除运行中容器,可以先执行stop后再删除 docker rmi //删除镜像编号,删除该镜像得先删除该镜像所有的容器-f可以删除多个容器,如果全部删除docker rmi -f $(docker images -aq) docker cp //可以从宿主机拷贝容器,也可以从容器拷贝宿主机 docker top //查看容器内的top命令 docker build //通过Dockerfile只做镜像-t 镜像名称 然后路径 .为当前路径 docker commit //提交当前镜像为新的镜像 docker save //保存一个镜像为tar包 docker tag //给docker中的镜像打标签 docker load //从一个tar包加载镜像 docker history //展示一个镜像的形成历史 docker diff //查看容器的变化 docker import //导出容器的内容流到一个tar归档文件tar归档文件 docker export //从一个tar归档文件tar归档文件导入创建为一个新的文件镜像
docker logs -ft --tail 10 97d71a3ecb35 //查看容器的日志 -ft显示日志 --tail 日志显示行数 docker exec -it 97d71a3ecb35 /bin/bash //进入容器内部 -it使用交互式方式运行,容器内执行exit退出 docker attach 97d71a3ecb35 //连接到正在运行中的容器,容器输出会打印控制台,ctrl+c终端退出容器也会停止 docker inspect 97d71a3ecb35 //查看容器/镜像的元数据如容器的主机配置、挂载、网络设置
docker-hub官网 需要注册docker的账号,页面搜索 elasticsearch,要部署其他软件也是类似操作
ES需要暴露端口较多,十分占用内存,数据需要放到安全目录,--net somenetwork进行网络配置,这些后面我们详细说明,这里只是引入概念入门理解
docker network create somenetwork //创建用户定义的网络(用于连接到连接到同一网络的其他服务(如Kibana)) docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.14.0 //运行Elasticsearch docker stats //查看容器的物理资源使用情况
访问ES 9200端口,这个是暴露ES RESTful接口端口号,http://192.168.3.117:9200/
我们通过-e设置虚拟机参数修改ES运行的内存
[root@localhost ~]# docker stop 0daa832636720daa83263672[root@localhost ~]# docker rm 0daa83263672[root@localhost ~]# docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms516m -Xmx1024m" elasticsearch:7.14.0 //运行Elasticsearch
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库,环境变量和配置文件, 所有的应用,直接打包docker镜像,就可以直接跑起来
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sA3YOxBS-1629904012586)(image-20210825135001005.png)]
docker 的理念将应用和环境打包成一个镜像, 如果数据都在容器中,那么我们容器被删除,数据就会丢失! 怎样可以把容器数据持久化
比如Mysql,docker设计了一个容器之间数据共享技术,Docker容器中产生的数据同步到本地 ---------这就是数据卷技术,目录的挂载,将我们容器的目录,挂载到Linux上面!简单说就是容器的持久化和同步操作,容器间也是可以数据共享的
一种方式是可以直接通过命令docker run -v方式挂载 ,挂载三种形式,也可以通过Dockerfile文件来实现挂载,这个下一小节再说
docker run -d -P --name nginx-itxs01 -v /etc/nginx nginx //匿名挂载 docker run -d -P --name nginx-itxs02 -v my_nginx:/etc/nginx nginx //具名挂载 docker run -d -P --name nginx-itxs03 -v /home/docker/root:/etc/nginx nginx //指定路径挂载!
挂载后我们便可以实现从宿主机上修改nginx.conf配置文件实现配置更改,放置页面实现静态资源的更新
Dockerfile 就是用来构建docker镜像的构建文件!通过这个脚本可以生成镜像,镜像是一层一层的,一个个的命令,每个命令都是一层!
先手工写一个简单Dockerfile并build成镜像,可以看到在容器内挂载两个目录
通过docker inspect也可以查看到挂载信息,如果在宿主机或者容器内修改挂载目录下的内容,两边都会数据同步
FROM--------------- # 基础镜像,一切从这里开始构建
MAINTAINER---- # 镜像是谁写的,姓名+邮箱
RUN --------------- # 镜像构建的时候需要运行的命令
ADD --------------- # 步骤:tomcat镜像,这个tomcat压缩包,添加内容
WORKDIR--------- #镜像的工作目录
VOLUME---------- #挂载的目录
EXPOST----------- # 保留端口配置
CMD----------------- # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT---- # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD----------- # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的命令,触发指令
COPY-----------------# 类似ADD 将我们文件拷贝到镜像中
ENV-------------------# 构建的时候设置环境变量
volumes-from 容器间传递共享
当我们在使用docker容器的时候,会产生一系列的数据文件,这些数据文件在我们关闭docker容器时是会消失的,但是其中产生的部分内容我们是希望能够把它给保存起来另作用途的,Docker将应用与运行环境打包成容器发布,我们希望在运行过程钟产生的部分数据是可以持久化的的,而且容器之间我们希望能够实现数据共享。通俗地来说,docker容器数据卷可以看成使我们生活中常用的u盘,它存在于一个或多个的容器中,由docker挂载到容器,但不属于联合文件系统,Docker不会在容器删除时删除其挂载的数据卷。
docker run -itd --name itsx_docker1 itxs/centos1 //第一个容器docker run -itd --name itsx_docker2 --volumes-from itsx_docker1 itxs/centos1 docker run -itd --name itsx_docker3 --volumes-from itsx_docker1 itxs/centos1
itsx_docker2和itsx_docker3都挂载,可以在itsx_docker2和itsx_docker3容器内查看到之前建的两个文件
删除itsx_docker1容器,在itsx_docker2和itsx_docker3容器内仍然可以查看到之前建的两个文件,实现容器之间的数据同步,删除itsx_docker2,itsx_docker3容器内仍然可以查看到之前建的两个文件,因此容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止,但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的
因此比如想实现Mysql数据同步就可以用这种方法实现
//-e 设置mysql root密码 docker run -d -p 3308:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql1 mysql:8.0 docker run -d -p 3304:3306 l -e MYSQL_ROOT_PASSWORD=123456 --name mysql2 --volumes-from mysql1 mysql:8.0
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、#表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交!
5、dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockfile文件!Docker镜像逐渐成为企业交付的标准,开发人员也必须掌握
从docker-hub查找镜像,并通过官方说明链接到GitHub地址,比如我们查找centos镜像
FROM scratch ADD CentOS-8-Container-8.1.1911-20200113.3-layer.x86_64.tar.xz / LABEL org.label-schema.schema-version="1.0" \ org.label-schema.name="CentOS Base Image" \ org.label-schema.vendor="CentOS" \ org.label-schema.license="GPLv2" \ org.label-schema.build-date="20200114" \ org.opencontainers.image.title="CentOS Base Image" \ org.opencontainers.image.vendor="CentOS" \ org.opencontainers.image.licenses="GPL-2.0-only" \ org.opencontainers.image.created="2020-01-14 00:00:00-08:00" CMD ["/bin/bash"]
Docker Hub中, 几乎绝大部分的镜像都是从这个基础镜像过来的 FROM scratch, 然后配置需要的软件和配置来进行的构建。
上面centos不能执行vim和ifconfig命令,我们制作一个镜像,编写Dockerfile文件,内容如下,然后编译镜像,运行容器使用vim和ifconfig命令查看成功
FROM centos MAINTAINER itxiaoshen@aaa.com ENV MYPATH /uer/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo “----finish----” CMD /bin/bash
docker build -t itxs/centos-tools . //编译镜像
FROM centos MAINTAINER itxiaoshen@aaa.com COPY readme.txt /uer/local/readme.txt ADD jdk-8u11-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.40.tar.gz /usr/local RUN yum -y update --nogpgcheck RUN yum -y makecache --nogpgcheck RUN yum -y install vim --nogpgcheck ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_11 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.40 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.40 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.40/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.40/bin/logs/catalina.out
docker build -t itxs-tomcat . docker run -d -p 8081:8080 --name itxstomcat1 -v /home/docker/data/tomcat/test:/usr/local/apache-tomcat-9.0.40/webapps/test -v /home/docker/data/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.40/logs itxs-tomcat
通过命令ip addr查看本地ip地址,我们发现除了本机回环地址和内网地址外,还多了一个网卡:Docker0,这是Docker服务启动后自动生成的。
之前我们从docker inspect 命令可以查看容器网络配置包括容器主机名和IP地址,docker宿主机和docker容器之间网络是连通的,可以在宿主机直接ping同容器的内网地址,并且容器和容器之间是也是可以互相ping通的,容器1→Docker0→容器2
原理:我们每启动一个docker容器,docker就会给容器分配一个默认的可用ip,我们只要安装了docker,就会有一个网卡docker0(bridge)。网卡采用桥接模式,并使用veth-pair技术(veth-pair就是一堆虚拟设备接口,成对出现,一段连着协议,一段彼此相连,充当一个桥梁)
docker中的所有网络接口都是虚拟的 ,转发效率高。删除容器后,对应的网桥也随之删除。
docker run -d -P --link 容器名/id 镜像名/id //直接使用容器名是无法ping通容器内部的,这时我们可以在容器启动命令中加入一个选项:--link,使得我们可以根据容器名来访问容器,但是如果反向就不可以ping通,这是因为--link的本质是把需要连接的容器名/id写入启动容器的配置文件中,即增加了一个ip和容器名/id的映射,实现原理也是往容器里系统/etc/hosts文件增加解析记录,--link使用场景较少,已不推荐 docker network ls //列出所有网络 docker中的网络模式有:bridge:桥接(docker默认);none:不配置网络 ;host:和宿主机共享网络 docker run 命令默认带有一个参数--net bridge,此处的bridge指的就是docker0。如果我们不想使用docker0,那就可以自己创建一个新的网络 docker network create --driver bridge --subnet 192.168.9.0/16 --gateway 192.168.9.1 testnet
只要两个容器启动时都通过 --net,选用了同一个已创建的网络,不同容器间即可通过ip地址或容器名/id连通:
那如果两个容器--net使用不同网络,那我们则需要通过docker network connect命令打通容器与网络之间的连接:最终ping通
[root@localhost centos-tool]# docker run -d --name nginx-test1 --net bridge nginx 75cc2e3d857ace3798e9e853b49fff66e3bdd87eaaba0d770a853ecf16242102 [root@localhost centos-tool]# docker run -d --name nginx-test2 --net testnet nginx 63e4a23762b01f7b30092d83cf268f6282d57d26e14eb67f54a9bf3c372e498a apt-get update apt-get install inetutils-ping //容器内安装ping命令
前面学习单个容器的操作,如果我们微服务是几十上百个且服务与服务之间也有依赖关系,应该怎么处理?docker compose容器编排就能轻松解决这些问题
还有如果服务需要部署到多台物理机上哪又应该怎么办,docker swarm作为docker官方集群管理可用来解决这些问题,后面还有docker stack 、docker config、docker secret 等;docker swarm适合于十几台内的小型集群规模应用,大规模集群应用即线上环境我们则直接是使用K8S,所以关于容器编排我们后续以K8S作为重点学习对象
docker进阶我们会先从官方Docker Compose官网 的入门案例入手,这里先踩个花絮,下次再见