Skip to content

一、概述

Docker是一种款苏将部署应用及应用所需的各种环境打包的技术。可以在服务器上快速部署项目,解决环境兼容的问题,并且多个服务之间相互隔离,互不影响。Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统

Docker是一个客户端-服务器(C/S)架构程序。Docker客户端只需要向Docker服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具Docker以及一整套RESTful API。你可以在同一台宿主机上运行Docker守护进程和客户端,也可以从本地的Docker客户端连接到运行在另一台宿主机上的远程Docker守护进程

image-20201129144852478

Docker daemon(Docker守护进程)Docker守护进程是部署在操作系统上,负责支撑Docker Container的运行以及本地Image的管理。
Docker client用户不直接操作Docker daemon,用户通过Docker client访问Docker,Docker client提供pull、run等操作命令。
Docker ImageDocker 镜像就是一个只读的模板。 例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了 Tomcat或用户需要的其它应用程序。 镜像可以用来创建 Docker 容器。 Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
Docker ContainerDocker 利用容器来运行应用。容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。打个比方,镜像相当于类,容器相当于对象。
Docker RegistryDocker 仓库分为公开仓库(Public)和私有仓库(Private)两种形式 最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。 用户也可以在本地网络内创建一个私有仓库。 当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。 网易云镜像服务阿里云镜像库

1.1 Docker镜像原理

Docker镜像本质是一个分层文件系统。docker的镜像复用操作系统的bootfs,只有rootfs和其他镜像层

  • Docker镜像是由特殊的文件系统叠加而成
  • 最底端是 bootfs,并使用宿主机的bootfs
  • 第二层是 root文件系统rootfs,称为base image
  • 然后再往上可以叠加其他的镜像文件
  • 统一文件系统(Union File System)技术能够将不同的 层整合成一个文件系统,为这些层提供了一个统一的视角 ,这样就隐藏了多层的存在,在用户的角度看来,只存在 一个文件系统。
  • 一个镜像可以放在另一个镜像的上面。位于下面的镜像称 为父镜像,最底部的镜像成为基础镜像。
  • 当从一个镜像启动容器时,Docker会在最顶层加载一个读 写文件系统作为容器

Linux文件系统

Linux文件系统由bootfs和rootfs两部分组成

  • bootfs:包含bootloader(引导加载程序)和 kernel(内核)
  • rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev, /proc,/bin,/etc等标准目录和文件 • 不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu ,centos等

二、创建镜像

2.1 Maven项目上传至Docker

插件配置

xml
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐maven‐plugin</artifactId>
</plugin>
<!‐‐ docker的maven插件,官网:
    https://github.com/spotify/docker‐maven‐plugin ‐‐>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker‐maven‐plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>192.168.184.141:5000/${project.artifactId}:${project.version}
</imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "‐jar",
"/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}
</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://192.168.184.141:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>

生成Dockerfile

dockerfile
FROM jdk1.8
ADD app.jar /
ENTRYPOINT ["java","‐jar","/app.jar"]

运行命令

shell
mvn install
# 打包上传


<NolebasePageProperties />




mvn docker:build ‐DpushImage

2.2 docker commit

以制作一个tomcat镜像为例:

制作步骤

shell
# 1、拉取一个基础镜像(其始就是OS)
docker pull centos

# 2、创建一个交互式容器
docker run -it --name=mycentos centos:latest

# 3、软件上传:将宿主机Tomact、jdk上传到容器中
docker cp apache-tomcat-7.0.47.tar.gz mycentos:/root/
docker cp jdk-8u161-linux-x64.tar.gz mycentos:/root/

# 4、在容器中安装jdk  
tar -zxvf jdk-8u161-linux-x64.tar.gz -C /usr/local/
# 编辑/etc/profile文件,添加如下内容:
JAVA_HOME=/usr/local/jdk1.8.0_161
export PATH=$JAVA_HOME/bin:$PATH

# 5、在容器中安装tomcat
tar -zxvf apache-tomcat-7.0.47.tar.gz -C /usr/local/
# 编辑tomcat/bin/setclsspath.sh文件,添加如下内容:
export JAVA_HOME=/usr/local/jdk1.8.0_161
export JRE_HOME=/usr/local/jdk1.8.0_161/jre

# 6、将正在运行的容器提交为一个新的镜像
docker commit mycentos mytomcat

端口映射

shell
docker run -itd --name=t1 -p 8888:8080 mytomcat /bin/bash
docker exec t1 /usr/local/apache-tomcat-7.0.47/bin/startup.sh

目录挂载

shell
# 1、启动容器t1
docker run -itd --name t1 mytomcat

# 2、完成目录映射
docker cp t1:/usr/local/tomcat7/webapps /opt/
docker cp t1:/uer/local/tomcat7/conf /opt/

# 3、停止容器t1并删除
docker stop t1
docker rm t1

# 4、启动一个新容器并且做目录挂载
docker run -itd --name t1 -p 9999:8080 -v /opt/webapps/:/usr/local/tomcat7/webapps -v /opt/conf/:/usr/local/tomcat7/conf mytomcat

# 3、启动容器中的tomcat
docker exec t1 /usr/local/tomcat7/bin/startup.sh

# 4、通过浏览器访问

# 5、设置宿主机/opt/webapps/下文件时,容器自动修改

容器/镜像打包

镜像打包

shell
# 1、镜像打包:
docker save -o /root/tomcat7.tar mytomcat
# 2、将打包的镜像上传到其他服务器
scp tomcat7.tar 其他服务器ip:/root
# 3、导入镜像
docker load -i /root/tomcat7.tar

容器打包

sh
# 1、容器打包
docker export -o /root/t1.tar t1
# 2、导入容器
docker import t1.tar mytomcat:latest

2.3 Dockerfile

详情参考

2.4 DockerCompose

详情参考

三、Docker命令

3.1 Docker相关

shell
# 启动docker
systemctl start docker
#停止docker
systemctl stop docker
# 重启docker
systemctl restart docker
# 查看docker状态
systemctl status docker
# 开机启动
systemctl enable docker
# 查看docker概要信息
docker info
# 查看docker帮助文档
docker --help
# 刷新配置
systemctl daemon‐reload

3.2 镜像相关

镜像都是存储在Docker宿主机的/var/lib/docker目录下

shell
#查看镜像
docker images
# 查看所用的镜像id
docker images -q
#REPOSITORY:镜像名称
#TAG:镜像标签
#IMAGE ID:镜像ID
#CREATED:镜像的创建日期(不是获取该镜像的日期)
#SIZE:镜像大小

#搜索镜像 从网络中查找
docker search 镜像名称
#NAME:仓库名称
#DESCRIPTION:镜像描述
#STARS:用户评价,反应一个镜像的受欢迎程度
#OFFICIAL:是否官方
#AUTOMATED:自动构建,表示该镜像由Docker Hub自动构建流程创建的

# 拉取镜像 centos:7
docker pull 镜像名称

## 删除镜像
# 根据ID删除镜像
docker rmi 镜像ID
# 删除所有镜像
docker rmi `docker images -q`
# 删除多个镜像
docker rmi 镜像名称1/id1 镜像名称2/id2 ...

# 将指定的镜像推到到docker仓库中。
docker push

# 制作镜像
#方式一:基于Dockerfile构建
docker builder(需要掌握DSL语法)
# 方式二:将运行的容器提交为一个新的镜像
docker commit(简单)
# 设置镜像标签
docker tag

3.3 容器相关

shell
## 查看容器
#查看正在运行的容器
docker ps
# 查看所有容器
docker ps –a
# 查看最后一次运行的容器
docker ps –l
#查看停止的容器
docker ps -f status=exited

## 创建容器
docker run
#参数:
# -i:表示运行容器
# -t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端。
# --name :为创建的容器命名。
# -v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
# -d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加-i -t两个参数,创建后就会自动进去容器)。
# -p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射

# 交互式创建容器
docker run -it --name=容器名称 镜像名称:标签 /bin/bash
# 退出当前容器
exit
# 守护式创建容器
docker run -di --name=容器名称 镜像名称:标签
# 登录守护式容器方式
docker exec -it 容器名称 (或者容器ID)  /bin/bash
docker attach 容器名称/id	

# 暂停容器
docker pause 容器名称(或者容器ID)
# 恢复运行
docker unpause 容器名称(或者容器ID)
## 停止容器
docker stop 容器名称(或者容器ID)
## 启动容器
docker start 容器名称(或者容器ID)

## 文件拷贝 系统与容器之间相互拷贝
#将文件拷贝到容器
docker cp 需要拷贝的文件或目录 容器名称:容器目录
# 将文件从容器内拷贝出来
docker cp 容器名称:容器目录 需要拷贝的文件或目录

## 目录挂载 将宿主机的目录与容器内的目录进行映射
# 注意:多级目录可能会出现权限不足的提示,需要将安全模块selinux权限禁用 或者添加参数--privileged=true 
# 创建容器 添加-v参数 后边为   宿主机目录:容器目录
docker run -di -v /usr/local/myhtml:/usr/local/myhtml --name=mycentos3 centos:7

# 获取容器运行数据
docker inspect 容器名称(容器ID) 
# 获取容器的ip
docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称(容器ID)
# 删除容器
docker rm 容器名称(容器ID)
# 删除多个容器:
docker rm 容器名称1/id1 容器名称2/id2 ...
# 删除所有容器
docker rm `docker ps -a -q`

# 查看容器日志
docker logs 容器名称/id

3.4 迁移备份

shell
# 将容器保存为镜像
docker commit mynginx mynginx_i
# 镜像备份 将镜像保存为tar文件
docker save -o mynginx.tar mynginx_i
# 镜像恢复
# -i 输入的文件
docker load -i mynginx.tar

3.5 数据卷相关

**数据卷(volume)**是一个虚拟目录,指向宿主机文件系统中的某个目录。

一旦完成数据卷挂载,对容器的一切操作都会作用在数据卷对应的宿主机目录了。对宿主机目录进行修改,等于操作容器的目录。

一个数据卷可以被多个容器同时挂载,一个容器也可以被挂载多个数据卷

shell
# 创建数据卷
docker volume create 数据卷名
# 显示所有数据卷
docker volume ls
# 显示一个或多个volume的信息
docker volume inspect 数据卷名
# 删除未使用的volume
docker volume prune 
# 删除一个或多个指定的volume
docker volume rm 

# 挂载数据卷
# `-v html:/root/htm` :把html数据卷挂载到容器内的/root/html这个目录中。也可直接使用目录
docker run --name mn -v html:/root/html 

# 数据卷容器 创建一个容器,挂载一个目录,让其他容器继承自该容器( --volume-from )
docker run –it --name=c3 –v /volume centos:7 /bin/bash
# 其他容器使用数据卷容器
docker run –it --name=c1 --volumes-from c3 centos:7 /bin/bash

# -v 挂载注意事项:目录必须是绝对路径,如果目录不存在,会自动创建。
# -v volume名称:容器内目录
# -v 宿主机文件:容器内文件
# -v 宿主机目录:容器内目录

数据卷与目录直接挂载区别:

  • 数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找
  • 目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看

四、docker网络管理

4.1 默认网络

1、查看docker网络:

shell
docker network ls

Docker中默认的三种网络分别为bridge、host和none,其中名为bridge的网络就是默认的bridge驱动网络,也是容器创建时默认的网络管理方式,配置后可以与宿主机通信从而实现与互联网通信功能,而host和none属于无网络,容器添加到这两个网络时不能与外界网络通信。

三种网络bridge、host和none都是在非集群环境下Docker提供的默认网络,而在Docker Swarm集群环境下,除了这三种默认网络外,Docker还提供了docker_gwbridge和ingress两种默认网络。

2、查看容器使用的网络情况:

shell
docker network inspect bridge

4.2 网络类型

  • Bridge networks(桥接网络):

    为了保证容器的安全性,我们可以使用基于bridge的驱动创建新的bridge网络,这种基于bridge驱动的自定义网络可以较好的实现容器隔离。需要说明的是,这种用户自定义的基于bridge驱动的网络对于单主机的小型网络环境管理是一个不错的选择,但是对于大型的网络环境管理(如集群)就需要考虑使用自定义overlay集群网络。

  • Overlay network in swarm mode(Swarm集群中的覆盖网络)

    在Docker Swarm集群环境下可以创建基于overlay驱动的自定义网络。为了保证安全性,Swarm集群使自定义的overlay网络只适用于需要服务的群集中的节点,而不会对外部其他服务或者Docker主机开放。

  • Custom network plugins(定制网络插件)

    如果前面几种自定义网络都无法满足需求时,就可以使用Docker提供的插件来自定义网络驱动插件。自定义网络插件会在Docker进程所在主机上作为另一个运行的进程。自定义网络驱动插件与其他插件遵循相同的限制和安装规则,所有插件都使用Docker提供的插件API,并且有一个包含安装、启动、停止和激活的生命周期。由于自定义网络插件使用较少,所以只需了解即可。

4.3 自定义网络

虽然Docker提供的默认网络的使用比较简单,但是为了保证各容器中应用的安全性,在实际开发中更推荐使用自定义的网络进行容器管理。在Docker中,可以自定义bridge网络、overlay网络,也可以创建network plugin(网络插件)或者远程网络以实现容器网络的完全定制和控制。

shell
# 1、创建一个基于bridge驱动的名称为isolated_nw的网络。其中--driver(可简写为-d)用于指定网络驱动类型,isolated_nw就是新创建的网络名称。需要说明的是,--driver bridge可以省略,省略时Docker会默认使用基于bridge驱动来创建新的网络。
docker network create --driver bridge isolated_nw

# 2、创建一个名为nwtest的容器,指令中的--network参数指定了该容器的网络连接为自定义的isolated_nw。通过docker inspect nwtest指令可以查看启动后的容器详情,来核查其网络管理方式.
docker run -itd --name=nwtest --network=isolated_nw busybox

# 3、为容器nwtest另添加一种默认的bridge网络管理方式。再次使用docker inspect nwtest指令查看该容器网络详情 
docker network connect bridge nwtest

# 4、断开网络连接的指令与连接网络的指令类似,在使用时也需要指定网络名称和容器名称
docker network disconnect isolated_nw nwtest

# 5、移除名称为isolated_nw的自定义网络。当网络移除成功后,会返回网络名称。
docker network rm isolated_nw

不同容器之间想要相互通信必须在同一个网络环境下;使用默认bridge网络管理的容器可以使用容器IP进行通信,但无法使用容器名称进行通信;而使用自定义网络管理的容器则可以使用容器IP进行通信

4.4 容器间的网络通信

sh
# 1、创建两个使用默认的bridge网络的容器
docker run -itd --name=c1 busybox
docker run -itd --name=c2 busybox

# 2、创建一个使用自定义的isolated_nw网络(需要预先创建)的容器
docker run --network=isolated_nw -itd --name=c3 busybox

# 3、为container2容器新增一个自定义的isolated_nw网络连接
docker network connect isolated_nw c2

五、Dockerfile

Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。

对于开发人员:可以为开发团队提供一个完全一致的开发环境 、对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件

5.1 常用命令

命令作用
FROM image_name:tag定义了使用哪个基础镜像启动构建流程
MAINTAINER user_name声明镜像的创建者
LABEL用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看
RUN command执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"]
CMD提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD ["command" , "param1","param2"]
ENTRYPOINT镜像中应用的启动命令,容器运行时调用。一般在制作一些执行就关闭的容器中会使用,可以多次设置,但是只有最后一个有效
COPY source_dir/file dest_dir/file和ADD相似,但是如果有压缩文件并不能解压
ADD source_dir/file dest_dir/file将宿主机的文件复制到容器内,如果是一个压缩文件,将会在复制后自动解压
ENV key value设置环境变量 (可以写多条)
ARG构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数
OLUME指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME ["目录"]
EXPOSE定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp
WORKDIR path_dir指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径
USER指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户
HEALTHCHECK指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制
ONBUILD当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大
STOPSIGNAL该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。
SHELL指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell
VOLUME设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,
这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。

5.2 使用脚本创建镜像

  1. 在要构建镜像的目录中引入项目,以jdk8为例

  2. 创建Dockerfile文件

    dockerfile
    #依赖镜像名称和ID
    FROM centos:7
    #指定镜像创建者信息
    MAINTAINER ITCAST
    #切换工作目录
    WORKDIR /usr
    RUN mkdir  /usr/local/java
    #ADD 是相对路径jar,把java添加到容器中
    ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
    
    #配置java环境变量
    ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
    ENV JRE_HOME $JAVA_HOME/jre
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
    ENV PATH $JAVA_HOME/bin:$PATH
  3. 执行构建命令

    shell
    docker build -t='jdk1.8' .#注意后边的空格和点,不要省略
  4. 查看镜像

    shell
    docker images

六、DockerCompose

Docker Compose是一个编排多容器分布式部署的工具,提供命令集管理容器化应用的完整开发周期,包括服务构建 ,启动和停止。使用步骤:

  1. 利用 Dockerfile 定义运行环境镜像
  2. 使用 docker-compose.yml 定义组成应用的各服务
  3. 运行 docker-compose up 启动应用

6.1 安装卸载

sh
# Compose目前已经完全支持Linux、Mac OS和Windows,在我们安装Compose之前,需要先安装Docker。下面我 们以编译好的二进制包方式安装在Linux系统中。 
curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 设置文件可执行权限 
chmod +x /usr/local/bin/docker-compose
# 查看版本信息 
docker-compose -version

# 二进制包方式安装的,删除二进制文件即可
rm /usr/local/bin/docker-compose

6.2 编写docker-compose.yml

Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。

示例:

创建一个镜像包含两个示例

  • mysql:一个基于mysql:5.7.25镜像构建的容器,并且挂载了两个目录
  • web:一个基于docker build临时构建的镜像容器,映射端口时8090
json
version: "3.8"
 services:
  mysql:
    image: mysql:5.7.25
    environment:
     MYSQL_ROOT_PASSWORD: 123 
    volumes:
     - "/tmp/mysql/data:/var/lib/mysql"
     - "/tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf"
  web:
    build: .
    ports:
     - "8090:8090"

启动容器

sh
# 在~/docker-compose 目录下 使用docker-compose 启动容器
docker-compose up

6.3 语法说明

DockerCompose的详细语法参考官网:https://docs.docker.com/compose/compose-file/

配置项(多级使用-/区分)描述
version通常在一个docker-compose.yml文件的最顶部,用来表示文件内容的约束版本(类似于XML文件约束)(版本越高,支持的指令越多)
services声明服务,在services下的所有同缩进的应用名称都代表一个服务,如6.2的web和mysql。
-/服务名-/image容器启动需要依赖的镜像(如果本地没有会自动pull)
-/服务名-/restart服务重启策略:
"no" #服务默认值为no,即服务失败后没有任何动作
always #表示服务会一直重新启动
on-failure #表示服务提示失败错误后会重新启动
unless-stopped #表示只有服务在停止后才会重启
-/服务名-/container_name指定容器名称
-/服务名-/ports指定服务向外暴露的端口
-/服务名-/networks指定容器使用的网络
-/服务名-/depends_on服务依赖决定了服务的依赖关系,如示例中的web依赖db,所以db服务会先于web服务启动,但并不表示db服务完全启动成功后才启动web服务,它只决定启动的先后顺序而已
-/服务名-/deploy针对Swarm集群部署提供的,子参数专门用于指定与服务部署和运行相关的配置
-/服务名-/deploy-/replicas表示服务实例的副本数量
-/服务名-/deploy-/restart_policy与restart类似,配置服务重启策略。该属性配置在deploy参数下,并只在集群环境下生效
-/服务名-/deploy-/conditionon-failure #表示服务重启的条件,值有none、on-failure和any
-/服务名-/deploy-/delay5s #表示重启服务之间等待时间,默认为0
-/服务名-/deploy-/max_attempts3 #表示失败后尝试重启的次数
-/服务名-/deploy-/window120s #表示等待多久来确定服务是否启动成功
-/服务名-/placement配置指定位置的约束,当服务在Swarm集群环境下部署时会随机分配到管理节点和其他工作节点上。在上述示例中由于将mysql数据挂载到了本机example-mysql数据卷中,所以使用了placement的子参数constraints: [node.role == manager]指定该服务只在manager管理节点上运行
-/服务名-/environment配置服务启动时需要的环境变量。如上述示例中MYSQL_ROOT_PASSWORD表示数据库root用户的密码,MYSQL_DATABASE表示数据库启动后自动创建的数据库。
-/服务名-/networks用于配置服务网络
-/服务名-/volumes目录挂载,上述示例中是将mysql数据挂载到本地example-mysql数据卷中,如果该数据卷不存在,服务启动时也会默认创建

七、仓库

7.1 公用仓库

docker hub

shell
#1、打开https://hub.docker.com/
#2、注册账号:略
#3、创建仓库(Create Repository):略
#4、设置镜像标签
docker tag local-image:tagname new-repo:tagname 
#eg:docker tag hello-world:latest 108001509033/test-hello-world:v1
#5、登录docker hub #(回车,输入账号以及密码)
docker login 
#6、推送镜像
docker push new-repo:tagname
# eg:docker push 108001509033/test-hello-world:v1

阿里云

略:参考官方文档。

shell
#步骤:
#1、创建阿里云账号
#2、创建命名空间
#3、创建镜像仓库
#4、操作指南
sudo docker login --username=[账号名称] registry.cn-hangzhou.aliyuncs.com
sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/360buy/portal:[镜像版本号]
sudo docker push registry.cn-hangzhou.aliyuncs.com/360buy/portal:[镜像版本号]

7.2 私有仓库

搭建

Docker Registry目前有v1和v2两个版本,v2版本并不是v1版本的简单升级,而是在很多功能上都有了改进和优化。v1版本使用的是Python开发的,而v2版本是用go语言开发的;v1版本本地镜像仓库容器中数据默认挂载点是/tmp/registry,而v2版本的本地镜像仓库容器中数据默认挂载点是/var/lib/registry

shell
# 拉取私有仓库镜像
docker pull registry

# 启动私有仓库镜像
#指令参数说明:
#-d:表示在后台运行该容器;
#-p 5000:5000:表示将私有镜像仓库容器内部默认暴露的5000端口映射到宿主机的5000端口
#--restart=always:表示容器启动后自动启动本地私有镜像仓库
#--name registry:表示为生成的容器命名为registry
#-v /mnt/registry:/var/lib/registry:表示将容器内的默认存储位置/var/lib/registry中的数据挂载到宿主机的/mnt/registry目录下,这样当容器销毁后,在容器中/var/lib/registry目录下的数据会自动备份到宿主机指定目录
# /var/lib/registry 是私有镜像库存放数据的目录
docker run -di --name=registry -p 5000:5000 -v registry-data:/var/lib/registry registry

#打开浏览器 输入地址http://ip:5000/v2/_catalog看到{"repositories":[]} 表示私有仓库搭建成功并且内容为空
# 修改daemon.json
{"insecure-registries":["ip:5000"]} 
# 重启docker
systemctl restart docker
docker start registry


# 重命名镜像,(之前推送镜像时,都是默认推送到远程镜像仓库)将指定镜像推送到本地私有镜像仓库。由于推送到本地私有镜像仓库的镜像名必须符合“仓库IP:端口号/repository”的形式,因此需要按照要求修改镜像名称。
docker tag hello-world:latest localhost:5000/myhellodocker

# 推送镜像,本地私有镜像仓库搭建并启动完成,同时要推送的镜像也已经准备就绪后,就可以将指定镜像推送到本地私有镜像仓库了
docker push localhost:5000/myhellodocker

# 查看本地仓库镜像
# http://localhost:5000/v2/myhellodocker/tags/list  (注意:使用该地址时注意镜像名称)

# 由于做了目录挂载,因此可以在本地的该目录下查看:
/mnt/registry/docker/registry/v2/repositories

部署图形化界面版本

带有图形化界面版本(使用DockerCompose部署)

yaml
version: '3.0'
services:
  registry:
    image: registry
    volumes:
      - ./registry-data:/var/lib/registry
  ui:
    image: joxit/docker-registry-ui:static
    ports:
      - 8080:80
    environment:
      - REGISTRY_TITLE=传智教育私有仓库
      - REGISTRY_URL=http://registry:5000
    depends_on:
      - registry

配置私有仓库认证

shell
#1、查看Docker Registry私有仓库搭建所在服务器地址:ifconfig
#例如:服务器地址为:192.168.200.141

#2、生成自签名证书(在home目录下执行上述指令后)
#要确保Docker Registry本地镜像仓库的安全性,还需要一个安全认证证书,来保证其他Docker机器不能随意访问该机器上的Docker Registry本地镜像仓库,所以需要在搭建Docker Registry本地镜像仓库的Docker主机上先生成自签名证书(如果已购买证书就无需生成),具体操作指令如下。
mkdir registry && cd registry && mkdir certs && cd certs

#指令参数说明:
#-x509:x509是一个自签发证书的格式
#-days 3650:表示证书有效期
#192.168.197.141:5000:表示具体部署Docker Registry本地镜像仓库的地址和端口
#rsa:2048:是证书算法长度
#domain.key和domain.crt:就是生成的证书文件
openssl req -x509 -days 3650 -subj '/CN=192.168.200.141:5000/' \
    -nodes -newkey rsa:2048 -keyout domain.key -out domain.crt



#3、生成用户名和密码
#在Docker Registry本地镜像仓库所在的Docker主机上生成自签名证书后,为了确保Docker机器与该Docker Registry本地镜像仓库的交互,还需要生成一个连接认证的用户名和密码,使其他Docker用户只有通过用户名和密码登录后才允许连接到Docker Registry本地镜像仓库
cd .. && mkdir auth
docker run --entrypoint htpasswd registry:2 -Bbn ruanwen 123456 > auth/htpasswd

# 4、启动Docker Registry本地镜像仓库服务(将之前创建的容器删除)
docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -v /mnt/registry:/var/lib/registry \
  -v `pwd`/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -v `pwd`/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2

# 5、配置Docker Registry访问接口
#完成Docker Registry本地镜像仓库服务启动后,还需要在搭建了Docker Registry本地镜像仓库所在的Docker主机上配置供其他Docker机器访问的接口,具体指令如下:
sudo mkdir -p /etc/docker/certs.d/192.168.200.141:5000
sudo cp certs/domain.crt /etc/docker/certs.d/192.168.200.141:5000

#6、Docker Registry私有仓库使用登记
#在Docker机器终端使用 命令编辑daemon.json文件,在该文件中添加如下内容
sudo vim /etc/docker/daemon.json
{"insecure-registries":["192.168.200.141:5000"]}

#7、重启并加载docker配置文件
sudo /etc/init.d/docker restart

二、验证测试
1、装备镜像
$ docker tag hello-world:latest 192.168.200.141:5000/myhelloworld
2、推送镜像
$ docker push 192.168.200.141:5000/myhelloworld

送过程中出现错误,信息提示为:no basic auth credentials(即没有通过身份验证),所以无法进行推送,这也就说明身份验证的配置有效。要想成功推送,需要先登录成功后再推送

3、登录Docker Registry镜像仓库
$ docker login 192.168.200.141:5000

4、再次推送
$ docker push 192.168.200.139:5000/myhelloworld

5、结果验证
由于做了目录挂载,因此可以在本地的该目录下查看:
/mnt/registry/docker/registry/v2/repositories

上传到私有仓库

shell
# 标记此镜像为私有仓库的镜像
docker tag jdk1.8 192.168.184.141:5000/jdk1.8
# 启动私服容器
docker start registry
# 上传标记镜像
docker push 192.168.184.141:5000/jdk1.8

如果送过程中出现错误,信息提示为:no basic auth credentials(即没有通过身份验证),所以无法进行推送

sh
# 登录Docker Registry镜像仓库
docker login 192.168.200.141:5000

# 再次推送
docker push 192.168.184.141:5000/jdk1.8

从私有仓库拉取

sh
#拉取镜像 
docker pull 私有仓库服务器ip:5000/centos:7

7.3 Harbor镜像仓库

Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。

  • 安装docker和docker-compose

  • 下载Harbor的压缩包 地址

  • 修改Harbor的配置 yml的ip和端口

  • 安装Harbor ./prepare ./install.sh

  • 启动Harbor

    sh
    docker-compose up -d 启动
    docker-compose stop 停止
    docker-compose restart 重新启动
  • 访问Harbor http://ip:85 默认账户密码:admin/Harbor12345

创建用户和项目

1)创建项目

Harbor的项目分为公开和私有的:

公开项目:所有用户都可以访问,通常存放公共的镜像,默认有一个library公开项目。

私有项目:只有授权用户才可以访问,通常存放项目本身的镜像。

2)创建用户

3)授权

进入项目 -》成员 -》 用户 -》 选择分配角色 -》 授权

访客 对于指定项目拥有只读权限

开发人员 对于指定项目拥有读写权限

维护人员 对于指定项目拥有读写权限,创建 Webhooks

项目管理员 除了读写权限,同时拥有用户管理/镜像扫描等管理权限

把镜像上传到Harbor

1)给镜像打上标签

sh
docker tag eureka:v1 192.168.66.102:85/tensquare/eureka:v1

3)把Harbor地址加入到Docker信任列表(不添加推送会报错)重启docker

sh
vi /etc/docker/daemon.json
{"registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"], "insecure-registries": ["192.168.66.102:85"] }

4)登录后再推送

docker login -u 用户名 -p 密码 192.168.66.102:85

2)推送镜像

sh
docker push 192.168.66.102:85/tensquare/eureka:v1

从Harbor下载镜像

1)修改Docker配置 并重启docker

sh
vi /etc/docker/daemon.json
{"registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"], "insecure-registries": ["192.168.66.102:85"] }

2)登录下载镜像

sh
docker login -u 用户名 -p 密码 192.168.66.102:85

docker pull 192.168.66.102:85/tensquare/eureka:v1

八、安装

Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docker出现的问题Ubuntu是最先更新或者打补丁的。在很多版本的CentOS中是不支持更新最新的一些补丁包的。

8.1 安装Docker

安装docker

shell
#yum 包更新到最新
sudo yum update
# 安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 --skip-broken
# 设置yum源为阿里云
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装docker
sudo yum install docker-ce
# 查看docker版本
docker -v

curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -add-apt-repository \
    "deb https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
    $(lsb_release -cs) \
    stable"
    
apt update

apt-get install -y apt-show-versions

apt-show-versions -a docker-ce

sudo apt-get update && apt-get install -y docker-ce

# 开机启动docker
sudo systemctl enable docker 
sudo systemctl start docker 

# 申请阿里云镜像加速器
# https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 
# 左侧镜像中心-》镜像加速器 右侧加速地址。

启动前需要关闭防火墙

shell
# 关闭
systemctl stop firewalld
# 禁止开机启动防火墙
systemctl disable firewalld

设置docker镜像下载源

ustc docker mirror不需要注册,是真正的公共服务。

shell
vi /etc/docker/daemon.json  

{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}

# 重载所有修改过的配置文件
sudo systemctl daemon-reload
# 重启Docker服务
sudo systemctl restart docker

8.2 卸载Docker

sh
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine \
                  docker-ce

8.3 安装DockerCompose

  • 下载

    shell
    # 安装
    curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    
    # 修改权限
    chmod +x /usr/local/bin/docker-compose
    
    # 补全命令
    curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
    # 如果出现错误,需要修改自己的hosts文件
    echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts
    
    
    # 查看docker compose版本
    docker-compose --version
    
    # PS:卸载docker compose
    sudo rm /usr/local/bin/docker-compose

8.4 搭建docker swarm集群

Swarm这个项目名称特别贴切。在Wiki的解释中,Swarm behavior是指动物的群集行为。比如常见的蜂群,鱼群,秋天往南飞的雁群都可以称作Swarm behavior。Swarm项目正是这样,通过把多个Docker Engine聚集在一起,形成一个大的docker-engine,对外提供容器的集群服务。同时这个集群对外提供Swarm API,用户可以像使用Docker Engine一样使用Docker集群。

Swarm是Docker公司在2014年12月初发布的容器管理工具,和Swarm一起发布的Docker管理工具还有Machine以及Compose。

Swarm是一套较为简单的工具,用以管理Docker集群,使得Docker集群暴露给用户时相当于一个虚拟的整体。Swarm将一群Docker宿主机变成一个单一的,虚拟的主机。Swarm使用标准的Docker API接口作为其前端访问入口,换言之,各种形式的Docker Client(docker client in Go, docker_py, docker等)均可以直接与Swarm通信。

Swarm几乎全部用Go语言来完成开发,Swarm0.2版本增加了一个新的策略来调度集群中的容器,使得在可用的节点上传播它们,以及支持更多的Docker命令以及集群驱动。

Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受docker客户端发送过来的请求,调度适合的节点来运行容器,这意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,当Swarm重新恢复运行之后,它会收集重建集群信息。

docker swarm特点:

  1. 对外以Docker API接口呈现,这样带来的好处是,如果现有系统使用Docker Engine,则可以平滑将Docker Engine切到Swarm上,无需改动现有系统。

  2. Swarm对用户来说,之前使用Docker的经验可以继承过来。非常容易上手,学习成本和二次开发成本都比较低。同时Swarm本身专注于Docker集群管理,非常轻量,占用资源也非常少。简单说,就是插件化机制,Swarm中的各个模块都抽象出了API,可以根据自己一些特点进行定制实现。

  3. Swarm自身对Docker命令参数支持的比较完善,Swarm目前与Docker是同步发布的。Docker的新功能,都会第一时间在Swarm中体现。

架构

Swarm作为一个管理Docker集群的工具,首先需要将其部署起来,可以单独将Swarm部署于一个节点。另外,自然需要一个Docker集群,集群上每一个节点均安装有Docker。

相关术语:

  • Swarm Manager:集群的管理工具,通过swarm manager管理多个节点。

  • Node:是已加入到swarm的Docker引擎的实例 。

    • manager nodes:也就是管理节点 ,执行集群的管理功能,维护集群的状态,选举一个leader节点去执 行调度任务
    • worker nodes,也就是工作节点 ,接收和执行任务。参与容器集群负载调度,仅用于承载task
  • 一个服务是工作节点上执行任务的定义。创建一个服务,指定了容器所使用的镜像和容器运行的命令。service是运行在worker nodes上的task的描述,service的描述包括使用哪个docker 镜像,以及在使用该镜像的容器中执行什么命令。

  • task任务:一个任务包含了一个容器及其运行的命令。task是service的执行实体,task启动docker容器并在容器中执行任务

docker swarm使用

搭建步骤:

  1. 准备三台已近安装docker engine的Ubuntu系统主机(docker版本必须在1.12以上的版本,老版本不支持swarm)
  2. docker容器主机的ip地址固定,集群中所有工作节点必须能访问该管理节点
  3. 集群管理节点必须使用相应的协议并且保证端口可用 集群管理通信:TCP,端口2377 节点通信:TCP和UDP,端口7946 覆盖型网络:UDP,端口4789 overlay驱动

搭建过程环境名称:

三台容器主机的ip地址分别为: 192.168.200.138(管理节点) 192.168.200.139(工作节点) 192.168.200.140(工作节点) 主机名称分别为:manager1、work1以及work2

shell
#2、创建docker swarm
#2.1、在manager1机器上创建docker swarm集群
# (--advertise-addr将该IP地址的机器设置为集群管理节点;如果是单节点,无需该参数)
docker swarm init --advertise-addr 192.168.200.138

# 2.2、查看管理节点集群信息:
docker node ls

#3、向docker swarm中添加工作节点:在两个工作节点中分别执行如下命令,ip地址是manager节点的
#3.1、添加两个work节点
# (--token xxx:向指定集群中加入工作节点的认证信息,xxx认证信息是在创建docker swarm时产生的)
docker swarm join --token xxx 192.168.200.138:2377  (worker1)
docker swarm join --token xxx 192.168.200.138:2377  (worker2)

# 3.2、继续查看管理节点集群信息与之前的区别
docker node ls

# 4、在docker swarm中部署服务
# 在Docker Swarm集群中部署服务时,既可以使用Docker Hub上自带的镜像来启动服务,也可以使用自己通Dockerfile构建的镜像来启动服务。如果使用自己通过Dockerfile构建的镜像来启动服务那么必须先将镜像推送到Docker Hub中心仓库。以下使用Docker Hub上自带的alpine镜像为例来部署集群服务
# 4.1、部署服务
# docker service create指令:用于在Swarm集群中创建一个基于alpine镜像的服务
# --replicas参数:指定了该服务只有一个副本实例
# --name参数:指定创建成功后的服务名称为helloworld
# ping docker.com指令:表示服务启动后执行的命令
docker service create --replicas 1 --name helloworld alpine ping docker.com

# 5.查看docker swarm集群中的服务
#查看服务列表:
docker service ls
#查看部署具体服务的详细信息:
docker service inspect 服务名称
#查看服务在集群节点上的分配以及运行情况:
docker service ps 服务名称

#6、修改副本数量
#在manager1上,更改服务副本的数量(创建的副本会随机分配到不同的节点)
docker service scale helloworld=5

#7、删除服务(在管理节点)
docker service rm 服务名称

#8、访问服务
#8.1、查看集群环境下的网络列表:docker network ls
#8.2、在manager1上创建一overlay为驱动的网络(默认使用的网络连接ingress)
docker network create -d=overlay my-multi-host-network
#8.3、在集群管理节点manager1上部署一个nginx服务
docker service create \
  --network my-multi-host-network \
  --name my-web \
  -p 8080:80 \
  --replicas 2 \
  nginx
#8.3、在管理节点查看服务的运行情况:
docker service ps my-web
8.4、访问测试

8.5 web可视化工具

当 Docker 部署规模逐步变大后,可视化监控容器环境的性能和健康状态将会变得越来越重要。 Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。常用工具如下:

1、docker UI(local)

2、shipyard(停止维护了)

3、portainer

4、daocloud

docker UI

安装docker UI

shell
1、拉取docker UI镜像
docker pull uifd/ui-for-docker

2、创建容器
docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
  • 优点:
    • 支持容器管理
    • 支持镜像管理
    • 基于docker api,自身也是一个容器。
    • 稳定性高
    • 可动态显示显示容器之间关系图
    • 容器管理,增加端口映射,增加系统变量、映射目录等
  • 缺点:
    • 没有登录验证,因为没有登录体系,目前解决办法是,只开放本地访问,或者通过TLS来对权限进行控制。
    • 无法分配某容器给某用户。
    • 不支持多主机。
    • 不支持集群swarm等
    • 功能少

portainer

安装portainer

shell
docker run -d -p 9001:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

挂载远程节点(修改远程节点配置)

shell
1、编辑该文件
vim /lib/systemd/system/docker.service

2、删除配置文件中内容
ExecStart=/usr/bin/dockerd xxx(删除这部分内容)

3、在daemon.json文件中添加如下内容:所有服务器都可以访问
"hosts":["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"]

4、重启docker
systemctl daemon-reload
systemctl restart docker

优点

  1. 支持容器管理、镜像管理
  2. 轻量级,消耗资源少
  3. 基于docker api,安全性高,可指定docker api端口,支持TLS证书认证。
  4. 支持权限分配
  5. 支持集群

缺点

  1. 功能不够强大。
  2. 容器创建后,无法通过后台增加端口。

daocloud

shell
执行该命令:
curl -sSL https://get.daocloud.io/daomonit/install.sh | sh -s 24a7c865945f25697fe9255dad8e54eb431d785b

优点:

  1. 支持镜像管理、容器管理。
  2. 支持控制台命令
  3. 容器资源消耗监控
  4. 支持集群可以随意增加节点
  5. 中文平台
  6. 镜像下载
  7. 容器扩容、管理

缺点

  1. 管理平台无法部署到本地服务器
  2. 部分高级功能收费

https://www.cnblogs.com/kevingrace/category/839227.html