(一)定义与介绍

前言:与虚拟机技术比较:

  • 虚拟机(VM):在docker容器技术出现之前使用的是虚拟机技术,将一台物理机虚拟化为多台机器,可搭载不同的操作系统。但每一个虚拟机系统的消耗较大,都需安装一个完整的内核,存储空间占用也多。且系统镜像也不支持版本控制。
  • Docker容器技术:docker的一大特点就是简单轻便,物理机(宿主机)只需要安装docker环境,拉取image镜像,则可以通过该镜像创建一个或多个系统实例(Docker称为容器,容器间相互隔离互不影响),且image镜像与虚拟机的系统镜像相比十分小。除此之外,镜像支持版本控制,Docker可以将容器进行commit提交形成一个新的镜像,可push到远端仓库,私人备份或公有到image仓库中。对于项目开发而言,idea可以配置dockerfile实现Java项目的自动化部署。

4大概念:容器(Container),镜像(Images),仓库(Repository),宿主机(物理机)

  • 仓库Repository:可指定配置源,是镜像存储的地方,可从此处拉取镜像(pull),或者将本地的镜像进行提交(push)
  • 镜像Image:系统或环境的镜像文件,可由其创建并运行(run)出容器实例(container)。镜像可从仓库拉取(pull)获得,或者从现有容器commit提交得到一份新的镜像Image
  • 容器Container:由镜像创建的容器实例,初始状态下各个容器实例环境相同,互不影响。容器分为两个状态:运行和停止
  • 宿主机(物理机):即就是运行docker环境的这台物理机

docker直接使用物理网络的ip段 docker物理机_docker直接使用物理网络的ip段

从公有仓库拉取的镜像可以进行自定义化,然后发布到公有仓库,或是自己的私有仓库上。

同一份镜像可以产生多个容器(实例),且这些容器初始环境完全相同,且互不影响,相互隔离(文件,ip等,进程)

(二)Docker环境配置

镜像源指定:为了下载更快,可指定为阿里云(将会影响docker search的结果和docker pull的速度)

阿里源Docker服务网站:阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

"registry-mirrors": [
    "https://8rzbqaxd.mirror.aliyuncs.com"
  ],
  • Windows下直接安装Docker Desktop即可

注意:

由于win10新版本提供了wsl2版的Linux,即Windows自带一个Linux内核,若Docker开启了wsl2的支持,则高级配置不会展示出:CPU,内存,磁盘,容器磁盘镜像目录等配置项。

docker直接使用物理网络的ip段 docker物理机_docker_02

Resources-Advance选项卡指定容器的配置,以及生成容器Container的磁盘镜像位置vhdx

docker直接使用物理网络的ip段 docker物理机_ubuntu_03

Resources-File Sharing选项卡指定共享文件夹,即将宿主机(物理机)的某些目录用来挂载到容器中,可供容器使用

docker直接使用物理网络的ip段 docker物理机_ubuntu_04

在Windows下的docker提供了两种container模式,可通过右键进行切换:但优先选择LinuxContainer

docker直接使用物理网络的ip段 docker物理机_ubuntu_05

  1. LinuxContainer:可运行基于Linux内核和Windows内核的容器(运用Hyper-V技术)
  2. WindowsConainer:仅可运行基于Windows内核的容器

Image镜像的下载目录在windows平台下不方便配置,因为在LinuxContainer模式下,镜像Image文件都是下载到一个虚拟的Linux目录中的(通过docker info命令可查),若为WindowsContainer模式,则可以配置。

  • Linux Ubuntu(18.04)下:
#若存在老版本先卸载之前的

sudo apt-get remove docker docker-engine docker.io containerd runc

#更新源

sudo apt-get update

#安装curl工具

sudo apt-get install curl

#添加docker的GPG密钥

curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

#验证密钥

sudo apt-key fingerprint 0EBFCD88

#安装添加源工具

sudo apt install software-properties-common

#指定仓库

sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

#再次更新源

sudo apt-get update

#安装docker-ce(社区版),cli客户端,以及解耦api

sudo apt-get install docker-ce docker-ce-cli containerd.io

验证docker环境:

docker -v 

#或者 

systemctl status docker

Ubuntu版的docker配置:

全局配置文件在:/etc/default/docker

sudo vim /etc/default/docker

修改镜像下载目录与修改容器磁盘镜像文件目录

默认配置可以通过docker info命令查看

docker直接使用物理网络的ip段 docker物理机_docker直接使用物理网络的ip段_06

该文件夹包含了下载的image和container文件夹

docker直接使用物理网络的ip段 docker物理机_ubuntu_07

若需要修改,则要修改:/etc/systemd/system/multi-user.target.wants/docker.service文件

sudo vim /etc/systemd/system/multi-user.target.wants/docker.service

docker直接使用物理网络的ip段 docker物理机_maven_08

修改为其他位置即可

配置阿里源:创建/etc/docker/daemon.json,并写入以下内容:然后重启服务systemctl restart docker

{
  "registry-mirrors": [
    "https://8rzbqaxd.mirror.aliyuncs.com"
  ]
}

(三)基本Docker命令

  • 镜像Images相关 (镜像名要求全小写)【一般为docker image xxx】

#获取当前所配置的源下,与输入的关键字相关的可提供下载的镜像(存放在远端的仓库)

docker search <关键字>

#按版本筛选(加标签)

docker search <关键字>:<tag>

例:docker search centos,docker search ubuntu:18.04

docker直接使用物理网络的ip段 docker物理机_docker_09

其中offical代表官方,automated代表自动构建产生的镜像

注意:官方镜像系统内容很少,有时缺少基本工具,如:ifconfig,ping,sudo之类,需要运行容器后自己安装

#拉取镜像

docker image pull <imageName/imageID>

#拉取镜像(指定版本),需到其官网查看他在docker hub上该版本的tag

docker image pull <imageName>:<tag>

#将镜像推送到远端仓库(imageName要求包含远端仓库地址)

docker image push <imageName>:<tag>

#查看所有已有的镜像

docker image ls

#创建容器并运行(最基础的)(可指定tag)

docker run --name <newContainerName> <imageName>:<tag>

#删除已有镜像(tag不为latest时,需要指定tag)【确保无本镜像创建的container】

docker image rm <imageName>

#镜像重命名

#此时会生成一个id相同的新镜像,手动删除之前不要的即可(可指定tag)

docker image tag <imageName> <newImageName>

#查看镜像详细信息(可指定tag)

docker image inspect <imageName>

  • 容器Container相关【一般为docker container xxx】

#查看容器列表(正在运行的)

docker container ls

#查看容器列表(所有的)

docker container ls -a

#运行已存在的容器

docker container start <containerName>

#停止某个运行的容器

docker container stop <containerName>

#重启某个容器

docker container restart <containerName>

#删除某个容器(确保该容器已停止运行)

docker container rm <containerName>

#容器重命名

docker container rename <containerName> <newName>

#进入某一正在运行容器(终端模式)

docker container exec -it <containerName> /bin/bash

#退出某容器(在容器终端中执行)

exit

#查看容器的占用情况(实时占用情况[CPU,RAM,NET])

docker container stats <containerName>

#查看某容器的详细信息(端口映射,磁盘映射,虚拟网段IP,维护者等等)

docker container inspect <containerName>

(四)容器的网络/存储隔离以及共享目录的配置

以下操作与image镜像本身无关,都是在执行run命令时配置(run配置参数只跟container实例,与image镜像无关)

  • 网络隔离(下能通上,上不通下【与路由器以路由方式嵌套理解相同】)

容器间网络互通(不管是不是由同一镜像产生的容器实例),因为他们在同一个虚拟网段下(默认在172.17.0.1),且这些容器都可以ping通宿主机(物理机)也可以通过物理机连接互联网(因为访问上层网络没有问题),但对于宿主机来说,其无法直接访问(ping通)任何一个容器,因为虚拟网段是模拟出来的,他是宿主机所在的下一级网段,没办法直接访问。

【这点和路由器之间以路由模式相接相同,假如192.168.1.1为一个路由,192.168.1.2为子路由,他的网关地址为192.168.123.1,其存在2个主机:192.168.123.2与192.168.123.3,此处通过192.168.1.x的主机直接直接访问192.168.123.x不可能访问成功,因为路由访问只能访问同级和上级的网络,只能访问192.168.123.x所属的上层网络ip:192.168.1.2,由该路由器配置DMZ/端口映射到其子层网络】

查看容器所在网段配置(类似于172.17.0.X)

docker network inspect bridge

docker直接使用物理网络的ip段 docker物理机_linux_10

【解决方案:对容器开启端口映射】

因此为了能让宿主机能访问【必然如此,不然在容器里运行的服务暴露不出来】,docker在执行run命令的时候提供了可配置的参数

#指定单个端口

docker run -dit --name <想取的容器名> -p <宿主机端口>:<容器内服务端口> <镜像名>

#指定多个端口

docker run -dit --name <想取的容器名> -p <宿主机端口>:<容器内服务端口> -p <宿主机端口>:<容器内服务端口> <镜像名>

注意:

  1. 只能在首次创建容器运行时(docker run命令)候指定端口映射,已有的容器无法添加
  2. 指定端口映射创建出来的容器container以后就直接启动,无需再次指定端口,只需确保宿主机端口未被占用即可开启
  3. 若实在要对已有容器container添加/修改端口映射,只能将当前容器提交commit为一个新的镜像,然后再用该镜像run一个新的容器(此时指定端口映射)

docker container commit <containerName> <newImageName>

  • 存储隔离

Docker容器Container实例之间的存储是相互隔离,互不影响的,容器Container产生的文件叫做磁盘镜像文件(DiskImage)这点和虚拟机相同,他的位置根据之前在DiskImageLocation目录:vhdx文件大小上限可以配置。默认64GB,所有容器Container实例的数据都存在这一个磁盘镜像文件中

docker直接使用物理网络的ip段 docker物理机_linux_11

  • 共享目录配置

Docker容器可共享使用宿主机(物理机)中的某一文件目录,该文件目录需要事先配置为共享文件夹,然后在首次创建并运行容器时追加-v参数进行指定(与端口映射相同,只能在这个时机指定)

[Windows指定共享目录]

(本步骤是对windows文件夹的权限指定,即让docker拥有以下文件夹权限)

docker直接使用物理网络的ip段 docker物理机_maven_12

[Linux(Ubuntu)指定共享目录]

无需额外配置,只需在docker run时指定-v参数即可

【磁盘映射参数(也可指定多个)】

#-v <宿主机目录>:<容器环境需要挂载的地方>

#例

docker run -dit --name testMultiFolderMapping -v E:/DockerShareFolder:/mnt/folder1 -v E:/Share:/mnt/folder2  ercircle/ubuntu_server

  • 超级权限(一般不需要)

在首次创建并运行run容器container实例时,添加以下参数:--privileged=true可以配置容器内环境具备超级管理员的权限。甚至允许在容器中再次搭建docker

--privileged=true 

#例 

docker run -dit --name Test --privileged=true ercircle/ubuntu_server

  • 指定时区(可安装后提交为镜像,以后直接使用这个镜像)

容器时间默认和宿主机相同,但时区使用的是UTC+0即太平洋时区,要改为东八区,由于docker容器的权限有限,需要安装tzdata来调整

sudo apt-get install tzdata

  • 配置某一容器自动启动

可以在首次docker run时追加参数,也可以对已有的container进行设置

#首次运行时指定该容器实例自启 

docker run --restart=always 

#对已有的容器设置为自启 

docker update --restart=always <CONTAINER ID>

(五)修改Docker镜像并push至库

核心概念:

  • 镜像的仓库没有版本控制,每一次提交都是一个新的镜像,新的镜像和之前没有关系(imageName相同,tag不同也算是不同的image)
  • 镜像Image本身不可修改,所谓的修改是对其生成的容器Container实例进行操作后,提交commit后为一个新的镜像

提交Commit命令:

#对于某镜像的容器实例修改后提交为一个新的镜像(镜像名可与之前的相同(但此时必须指定tag【一般设置为版本号】))

docker container commit -m "本次提交内容" -a "作者信息" <containerName> <newImageName>:<可指定tag(代表版本)>

配置阿里云镜像管理服务:

将自己的镜像push到阿里云镜像管理服务中(自己的远端镜像仓库)

官网:阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

(1)准备工作:配置账户密码,创建命令空间,确定好地域节点名

(2)创建命名空间,创建镜像仓库(使用本地仓库模式)

(3)执行docker命令登录到目标节点:

docker login --username=五航战瑞鹤酱 registry.cn-shanghai.aliyuncs.com

(4)列出本地镜像,确定要提交的镜像id或者名字,执行tag操作修改image名

Tag后原image不影响,依然存在,会产生一个imageId相同,imageName为新设置的镜像,新设置的镜像name需要指定为固定格式:地域节点/com/命名空间/镜像仓库名:,tag一般指定为版本号

docker直接使用物理网络的ip段 docker物理机_docker直接使用物理网络的ip段_13

docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/zuikaku/pilipili-web-ubuntu:1.0

(5)执行提交push操作

docker push registry.cn-shanghai.aliyuncs.com/zuikaku/pilipili-web-ubuntu:1.0

push完成后,在镜像版本中可以看到这次push的记录,未指定tag,则默认为latest(最新的)

docker直接使用物理网络的ip段 docker物理机_docker_14

如果后续需要拉取,则到基本信息中:执行docker pull

docker pull registry.cn-shanghai.aliyuncs.com/zuikaku/init-ubuntu:<镜像版本号>

(六)在项目中使用dockerfile实现自动化部署

[1]修改docker.service

Ubuntu版的docker目录在:/etc/systemd/system/multi-user.target.wants/docker.service

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

docker直接使用物理网络的ip段 docker物理机_ubuntu_15

修改完后重新应用

systemctl daemon-reload systemctl restart docker

访问2375端口进行验证

docker直接使用物理网络的ip段 docker物理机_linux_16

[2]项目中配置docker

  • pom.xml添加docker的maven插件依赖
<!--使用docker-maven-plugin插件-->

<plugin>

    <groupId>com.spotify</groupId>

    <artifactId>docker-maven-plugin</artifactId>

    <version>1.0.0</version>

    <configuration>

        <!--指定生成的镜像名-->

        <imageName>nanoda/${project.artifactId}</imageName>

        <!--指定标签(一般为版本)-->

        <imageTags>

            <imageTag>1.2</imageTag>

        </imageTags>

        <!-- 指定 Dockerfile 路径:项目根目录-->

        <dockerDirectory>${project.basedir}</dockerDirectory>

        <!--指定远程 docker api地址-->

        <dockerHost>http://www.zuikakuedu.top:2375</dockerHost>

    </configuration>

</plugin>
  • 项目根目录添加Dockerfile文件

docker直接使用物理网络的ip段 docker物理机_ubuntu_17

Dockerfile的组成成分:


#指定以哪个image作为初始镜像(此处可指定为公有仓库链接)【推荐先在宿主机把该image事先pull下来,避免docker build时因权限不足的报错】

FROM <镜像远端地址>

#指定该镜像的维护者信息

MAINTAINER <维护者姓名> <联系邮箱(可选)>

#添加哪些文件到目标镜像的目录(一般添加jar包,为tar时会自动解压,镜像环境的目录不存在时会自动创建)

ADD <以项目目录根目录下的文件或目录(相对路径)> <镜像环境的目标目录(绝对路径)>

#指定需要在目标镜像产生的容器中执行的初始化操作(可按顺序指定多条)

RUN <Linux命令1>

RUN <Linux命令2>

#指定需要暴露的端口(仅声明要暴露的端口,方便-P自动映射,手动映射依然需要在run时指定-p参数)

EXPOSE <端口1> <端口2>

#指定挂载点,自动实现路径映射,宿主机地址为随机生成(可通过docker container inspect查看,若要手动指定需要run时指定-v参数)

VOLUME ["/mnt/folder1","/mnt/folder2"]

#指定环境,如JDK,Tomcat目录,编码环境等

ENV LANG C.UTF-8

#指定容器创建完成的运行的命令,容器从关闭状态变为启动后执行的命令(一般用于启动某程序,或者执行某shell)

ENTRYPOINT ["Linux命令","参数1","参数2",...]

案例:

FROM registry.cn-shanghai.aliyuncs.com/zuikaku/ubuntu1804-init-env:1.0
MAINTAINER  nanoda tanyu159@live.com
ADD target/oc-0.0.1-SNAPSHOT.jar /home/admin/ZuikakuOnlineCourse/oc.jar
RUN mkdir /home/admin/ZuikakuOnlineCourse/storage
EXPOSE 9091
ENV LANG C.UTF-8
ENTRYPOINT ["nohup","java","-jar","/home/admin/ZuikakuOnlineCourse/oc.jar",">log.txt","&"]

【3】先执行项目package打包

Maven-Package执行打包生成target,确认jar包存在

docker直接使用物理网络的ip段 docker物理机_docker_18

docker直接使用物理网络的ip段 docker物理机_maven_19

【4】再执行docker build操作(如果需要重新build,需先进行maven-clean重新打包在docker build,清除docker的一些临时文件)

docker直接使用物理网络的ip段 docker物理机_docker_20

docker直接使用物理网络的ip段 docker物理机_docker直接使用物理网络的ip段_21

【5】回到宿主机docker run该新镜像

docker直接使用物理网络的ip段 docker物理机_maven_22

docker run -dit --name zuikaku-oc -p 9091:9091 -v /home/admin/ZuikakuOnlineCourse/storage/:/home/admin/ZuikakuOnlineCourse/storage nanoda/oc:1.1

特别注意:

可以发现,在进行docker自动化部署,开启2375端口,在项目中指定目标地址:端口,直接执行docker build命令是没有任何身份验证的,这也就说明存在漏洞,黑客可以扫描公网ip及其该端口注入内容,因此2375端口不应在公网开启,仅在局域网内访问,应该挂入vpn或者使用堡垒机的方式进行网络连接,实现docker build

(7)docker可视化管理工具portainer

portainer提供了一种可视化管理docker的方式,本质是一个网页后台,其本身也是作为docker的image存在,使用流程如下:

【1】搜索该镜像:docker search portainer

docker直接使用物理网络的ip段 docker物理机_ubuntu_23

【2】拉取该镜像:docker image pull portainer/portainer

【3】运行该镜像:需指定端口映射,容器内端口为9000,并开启超级权限和目录映射

docker run -d --name portainerUI -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

【4】放开防火墙,在外网访问该服务

docker直接使用物理网络的ip段 docker物理机_docker_24