1.在软件开发中,最麻烦的事情之一就是环境配置。在正常情况下,如果要保证程序能运行,我们需要设置好操作系统,以及各种库和组件的安装。 2.举例来说,要运行一个Python程序,计算机必须要有 Python 引擎,还需要安装好程序的各种依赖,甚至还要配置特定的环境变量。假设你有两个程序都需要部署在同一个服务器上,一个需要软件是基于Python2.0,一个是Python3.0,那么在部署上就很容易造成混乱。因为不同版本的Python模块可能互不兼容,况且不同开发环境上的库也需要额外的配置。如果要部署很多程序,而开发环境和部署环境各不相同的话,可想而知配置得多么麻烦。 3.为了更好地将软件从一个环境移植到另一个环境上,必须从根源上解决问题,那么如何在移植软件的时候,将一模一样的原始环境迁移过来呢?
虚拟机是移植环境的一种解决方案。虚拟机本质上也是一个软件,在这个软件中,我们可以运行另一种操作系统。比如我们想要在 MacOS 上运行 Linux 系统,我们就在电脑上安装 Linux 镜像,并使用虚拟机打开此镜像,就能创建出一个镜中镜了。这个方案非常方便,想要新环境,就安装镜像,然后使用虚拟机打开,不想要直接删除。但是这个方案有几个缺点:
为了解决虚拟机存在的这些缺点,Linux发展出了另一种虚拟化的技术:Linux容器。Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。或者说,就是在正常进程的外面套用了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层程序的隔离。由于容器是进程级别的,相比虚拟机有更多优势:
Docker属于Linux容器的一种封装,提供简单易用的容器使用接口,它也是目前最流行的Linux容器解决方案。Docker 将软件代码和其依赖,全打包在一个文件中。运行单个文件,就会生成虚拟容器。在这个虚拟容器中,不管本地的操作系统是如何的不同,此容器都能照常运行。 简而言之,Docker的接口非常简单,可以帮助用户更好地创建和使用容器,让相同的代码在不同的环境上正常运行。
Docker容器和传统VM技术,在技术实现上有所不同。下图显示的是VM与Docker容器的逻辑组成:
Server:相当于云服务器 Host OS:为操作系统 Docker Engine:可以认为我们在这个操作系统上安装了一个docker的软件 App A:在Docker组件中运行App A App B:在Docker组件中运行App B
# 所以docker完全没有操作系统的概念,用的还是宿主机的操作系统,但是它做出了隔离。也实现了虚拟化。
虚拟机与Docker容器对比
Docker容器的运行逻辑如下图所示,Docker使用客户端/服务器 (C/S) 架构模式,Docker守护进程(Docker daemon)作为Server端接收Docker客户端的请求,并负责创建、运行和分发Docker容器。Docker守护进程一般在Docker主机后台运行,用户使用Docker客户端直接跟Docker守护进程进行信息交互。
其中:
Docker是一个客户端-服务端(C/S)架构程序,Docker客户端只需要向Docker服务器或者守护进程发送请求即可,服务器或者守护进程将完成所有工作并返回结果,Docker提供了一个命令行工具以及一正太Restful Api,我们可以在同一台宿主机上运行Docker守护进程和客户端,也可以从本地Docker客户端连接运行在另外一台宿主机的Docker的守护进程。
# 使用了RESTful API的目的就是为了统一规范,无需自己在生成一套体系。现在几乎所有的软件都是通过RESTful API来传输数据。
1.有了镜像---》镜像运行起来是容器(真正的执行单位) 镜像 : 面向对象的类 容器 : 对象 2. 镜像是从哪里来的? -镜像就是一堆文件 -从远程仓库获取(拉取)
Docker是一个客户端-服务器(C/S)架构程序(mysql,redis都是cs架构),整套RESTful API
•Docker客户端(Docker Client)是用户与Docker进行交互的最主要方式。当在终端输入docker命令时,对应的就会在服务端产生对应的作用,并把结果返回给客户端。Docker Client除了连接本地服务端,通过更改或指定DOCKER_HOST连接远程服务端。
•Docker Daemon其实就是Docker 的服务端。它负责监听Docker API请求(如Docker Client)并管理Docker对象(Docker Objects),如镜像、容器、网络、数据卷等
•俗称Docker仓库,专门用于存储镜像的云服务环境.
•Docker Hub就是一个公有的存放镜像的地方,类似Github存储代码文件。同样的也可以类似Github那样搭建私有的仓库。
•镜像:一个Docker的可执行文件,其中包括运行应用程序所需的所有代码内容、依赖库、环境变量和配置文件等。
•容器:镜像被运行起来后的实例。
•网络:外部或者容器间如何互相访问的网络方式,如host模式、bridge模式。
•数据卷:容器与宿主机之间、容器与容器之间共享存储方式,类似虚拟机与主机之间的共享文件目录。
docker pull : 拉取镜像(从远程仓库中获取放到Images) docker run : 运行镜像(运行镜像后就会放到容器里) docker container : 查看运行了那些镜像(容器) docker image : 查看有那些镜像 docker network : 查看网络 docker valume : 查看数据表等 - 数据表等建议放到宿主机上,因为如果一旦容器删除了,在容器上的数据表就没有了。
1.镜像:就是一个只读的模板,镜像可以用来创建docker容器,一个镜像可以创建很多容器 2.容器:用镜像创建的实例,可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、网络空间等)和运行在其中的应用程序。容器与镜像的关系类似于面向对象编程中的类和对象,镜像好比是类,那么容器则是对象 3.仓库是集中存放镜像文件的场所。仓库(repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。仓库又分为公开仓库(public)和私有仓库(private)两种形式。最大的仓库是DockerHub (https://hub.docker.com),存放了数量庞大的镜像供用户下载。国内的公有仓库包括阿里云、网易云等。 docker本身就是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎image镜像文件。只有通过镜像文件才能生成docker容器。image文件可以看做是容器的模板。docker根据image文件生成容器实例。同一个image文件,可以生成多个可以同时运行的容器实例。 image文件 生成的容器实例,本身也是一个文件,称为镜像文件 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器。 仓库就是放了一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候从仓库中拉下来就可以
1 windows安装(不建议你装)http://get.daocloud.io/
# 0 卸载 sudo apt-get remove docker docker-engine docker.io containerd runc # 1 安装必要工具 sudo apt-get update sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common # 2 安装GPG证书 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - #换成阿里云 curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - # 2 写入软件源信息 #官方 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" #换成阿里云 sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" # 3 更新并安装docker-ce sudo apt-get -y install docker-ce # 4 开启docker服务 systemctl status docker # 安装成功后,使用 docker version查看 如果出现权限禁止,需要切换到root用户执行 su 输入密码 docker version
0 卸载(如果没有安装过无需卸载) yum remove docker docker-common docker-selinux docker-engine rm -rf /var/lib/docker 1 更新yum yum update 2 安装需要的软件包:yum-util (会生成该命令yum-config-manager) 命令:yum install -y yum-utils device-mapper-persistent-data lvm2 3 执行(向你的yum源,增加一条记录) yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 4 安装 yum install docker-ce 5 验证安装(查看版本) docker -v ~]# docker -v (19年03月12日发布) # 自从分了docker-ce和docker-ee以后,以年份命名版本 Docker version 19.03.12, build 48a66213fe
注意:自从区分docker-ce和docker-ee之后,docker最初始的版本是17.03,也就是17年发布的,所有17是老版本和新版本的分水岭
6 启动docker服务 systemctl start docker 7 停止docker服务,重启docker服务 systemctl stop docker systemctl restart docker 8 开机启动 systemctl enable docker 9 查看概要信息 docker info(你可能写了一个管理docker的运维平台)
下载镜像:
# 远程仓库地址:https://hub.docker.com/ - 注册 登录 # 你可以上传镜像(类似于github),你把你制作的镜像传上去,别人可以下载使用
# 搜索镜像: 方式一:https://hub.docker.com/ 点点点搜索 方式二:docker search 镜像名字 # 后面有OK代表官方
# search作用: 搜索Docker Hub(镜像仓库)上的镜像 # 命令格式: docker search [OPTIONS] TERM # 命令参数(OPTIONS): -f, --filter filter 根据提供的格式筛选结果 --format string 利用Go语言的format格式化输出结果 --limit int 展示最大的结果数,默认25个 --no-trunc 内容全部显示 # 命令演示 docker search -f is-offical=true ubuntu docker search ubuntu
# 拉取下载镜像 docker pull hello-world # 最新版本latest docker pull hello-world:nanoserver # 指定版本
docker pull hello-world:版本号(默认最新,可以指定版本号)
查看镜像
# 查看机器上有哪些镜像 # 命令:docker images # 解释: REPOSITORY TAG IMAGE ID CREATED SIZE 镜像名字 版本 id号 创建时间 大小
运行镜像
# 命令: docker run 镜像名字 docker run hello-world # 例: 第一个hello-world(没有任何意义) docker run hello-world 1 客户端连到服务端,服务下载了hello-world镜像 2 通过镜像跑起容器来 3 容器输出一些东西,通过服务端发送给客户端,客户端展示在窗口里了
删除镜像
# 命令: docker rmi 镜像名字/Id号 # 注意: 1.如果还有基于这个镜像的容器,是不允许删除镜像的 2.可以先删除容器,在删除镜像 # 查询容器依赖 docker ps -a # 在删除要不允许的镜像 docker rm 容器/id
# 拉取python3.6镜像,redis最新镜像,mysql5.7镜像 docker pull python:3.8 docker pull redis docker pull mysql:5.7 docker pull nginx docker pull centos:centos7 # 查询当前镜像 docker images
镜像容器是可以看作: -镜像就是一堆文件,这堆文件通过docker跑起来,就是容器,你现在就把他当成,一个操作系统内跑了这个软件(比如就是:centos+redis) -假设centos7的镜像跑起来,此时容器你就当成在你宿主机上跑了一个centos7的操作系统(虚拟机)
1 删除容器 docker rm 容器名字/容器id 2 启动并运行容器 # 通过centos:centos7镜像,创建一个容器名字叫mycentos,并且把它运行起来 docker run -di --name=mycentos centos:centos7 # 结果:会打印出容器的id号 3 查看机器上正在运行的容器 docker ps 4 查看宿主机上所有的容器(包括停止的) docker ps -a 5 停止容器 docker stop 容器名字/id号 6 启动容器 docker start 容器id/名字 # id号只要能够区分即可无需写全部
# 配置加速(之前去https://hub.docker.com/),阿里云,清华,做了一个备份,配置好以后,再拉镜像会去国内地址拉取 第一步:vi /etc/docker/daemon.json 第二步: # 指定清华源,提升拉取加速 { "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] }
# 作用: 利用镜像创建出一个Created 状态的待启动容器 # 命令格式: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] # 命令参数(OPTIONS):查看更多 -t, --tty 分配一个伪TTY,也就是分配虚拟终端 -i, --interactive 即使没有连接,也要保持STDIN打开 --name 为容器起名,如果没有指定将会随机产生一个名称 # 命令参数(COMMANDARG): COMMAND 表示容器启动后,需要在容器中执行的命令,如ps、ls 等命令 ARG 表示执行 COMMAND 时需要提供的一些参数,如ps 命令的 aux、ls命令的-a等等 # 创建容器命令演示: docker create --name test-container centos:centos7 ps -A # 我们创建了一个容器,并指定在启动容器的时候执行:docker ps -a docker create -ti --name test-container2 centos /bin/bash
# 作用: 将一个或多个处于创建状态或关闭状态的容器启动起来 # 命令格式: docker start [OPTIONS] CONTAINER [CONTAINER...] # 命令参数(OPTIONS): -a, --attach 将当前shell的 STDOUT/STDERR 连接到容器上 -i, --interactive 将当前shell的 STDIN连接到容器上 # 命令演示: docker ps -a docker start -a 65ebc docker start test-container
# 容器一直运行的原因COMMAND 1.它有一条前台进程,一直在运行 2.以后如果自己制作的镜像,运行起容器,必须有个可以夯住的命令COMMAND 3.如果COMMAND该命令结束,该容器也就结束了
# 当我们在后台启动的时候 1.比如:docker run -di --name=mycentos centos:centos7 2.这时他会自动启动一个 /bin/bash窗口 3.因为我们并没有关闭这个/bin/bash窗口,所以他会一直在后台运行 4.我们在使用start或者直接run进入这个镜像的时候,就相当于运行的这个命令:/bin/bash,就进入了这个bash窗口,相当于进入了容器(其实不是进入了容器,可以把他看作是xshell一个远程连接,连接到这个容器。)这里我们看作是进入到了这个容器,当我们使用exit退出的时候,就相当于关闭了/bin/bash这个窗口。所以容器一直会在后台运行的原因就是这个/bin/bash窗口一直在启动这,没有关闭它
# 创建并启动(run) # 参数: -i:表示运行容器 -t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端。 -d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加-i -t两个参数,创建后就会自动进去容器)。 --name :为创建的容器命名。如果不写,会自动分配一个名字(英文人名) -v:表示目录映射关系(前者是宿主机目录,后者是容器目录,映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。(下述单独演示) -p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射 (下述单独演示) # 例子:run docker run -it --name=myredis redis # 这时就会启动redis容器并进去redis容器 docker run -id --name=oursql mysql # 这时就不会进入mysql容器,再后台运行 # 注意,docker run 镜像 使用该命令:如果本地没有,会先pull,再run
# 方式1: 1.查询机器上运行的容器 docker ps 2.进入容器 docker exec -it 容器id/bin/bash docker exec -it 427 /bin/bash # 第二种:ssh连接(容器内部装ssh服务端)(不常用)
# exec真正的作用是在容器内执行命令,而不是真正的进入到容器内部 1.因为 /bin/bash这个命令,就相当于与这个容器建立了连接,所以我们可以和容器做交互,当我们关闭这个连接的时候,就会自动结束掉这个容器。 2.执行exec命令: docker exec -it 容器id ls # 查询根路径所有文件
# top 命令(容器内部执行查询进程)
# 容器内部是纯净的空间,安装:vim
# 命令:exit 1.如果是一个夯在哪里得命令,则使用exit退出容器 2.如果不是则会自动退出容器
# -it 进入容器退出(前台容器自动结束【后台停止运行】) 1.在我们使用 -it 参数直接进入该容器的时候,使用exit退出的时候这个容器就会自动结束。 - 此时后台就没有该运行中的容器。 # -id 进入容器退出(前台容器自动结束【后台正常运行】) 2.如果使用 -id 后台运行容器的时候,使用 docker exec进入该容器,此时使用exit退出该容器的话,只是退出该容器,并没有从后台结束该容器,该容器还会在后台运行这。
# 1.从宿主机拷贝到容器内部 docker cp 宿主机文件 容器id:容器路径 docker cp /home/a.txt 427:/home # 2.从容器中拷贝到宿主机 docker cp 容器id:容器路径 宿主机路径(起别名) docker cp 427:home/a.txt a.txt
# 目录挂载格式: docker run -di --name=mycentos99 -v /宿主机要挂载目录:/容器要挂载路径 指定镜像 docker run -di --name=mycentos99 -v /home:/home centos:centos7 # -v : 映射 # 挂载作用: 1.一旦挂载,以后宿主机目录内修改,同样影响容器内部 2.容器内修改同样影响宿主机
# 命令: - 使用参数 -p 宿主机端口:容器端口 - 例:docker run -it -p 6377:6379 redis # 将宿主机得6377端口映射到容器redis6379端口上
# 演示:
# 创建容器 - docker run -di -p 6377:6379 redis # 进入容器 - docker exec -it 27d /bin/bash - 此时启动的是redis服务端 # 连接客户端 - redis-cli # 在容器中操作redis - set name born
# 此时我们使用远程连接我们得宿主机云服务器的6377端口。
# 为什么会后台启动redis服务? 1.我们在启动redis容器的时候,他会自动运行一个脚本文件:docker-entrypoint.sh 2.就像启动cent os自动启动一个/bin/bash窗口 3.而redis启动/bin/bash与之建立连接之后,会自动执行这个脚本文件
# docker-entrypoint.sh 这个脚本的路径: /usr/local/bin/docker-entrypoint.sh
# 命令: # 查看容器详细信息 - docker inspect 容器id # 只查看容器ip地址 - docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称/容器ID
# 其实宿主机与容器之间是通过网关进行通信的 - 查看网关 # 容器内下载该命令: - 下载查看ip信息的命令:yum install net-tools - ifconfig:查看网络相关信息
# 所以此时我们在连接redis的时候就有两种方式 - 第一种: - 因为我们做了端口映射,所以我们可以通过:云服务器地址:6377连接 - 第二种: - 此时我们已经知道了容器的ip地址,所以就可以通过: 容器的ip地址:6379 (此时端口号就是它本身的6379因为是直接通过它本身的ip建立的连接)
# 每个容器都有ip地址,每一个ip地址标志着一台唯一服务器,所以就实现了宿主与容器之间的隔离性,每一个容器就相当于一个虚拟机
# 在容器内部署mysql # 容器内查询env,环境变量密码 docker run -di --name=mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 # -e : 表示环境变量指定密码 # 进入容器 docker exec -it 749 /bin/bash mysql mysql -uroot -p 123456 show databases; drop database lqz; # 官方提供的 docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag # 宿主部署容器内redis docker run -di -p 6377:6379 redis:latest # 宿主部署容器内nginx docker run -di --name=mynginx -p 8080:80 nginx # 我们都使用了 -p 参数做了端口映射,所以我们在访问云服务器指定映射端口后,就访问到部署好的容器,所以有了docker完全就需要在本地下载这些应用,直接使用docker pull拉下来使用即可