Docker的安装与使用

什么是Docker?

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app), 更重要的是容器性能开销极低。

关键字:容器虚拟化技术

需要准备

  • Centos7.x系统、64位系统、内核版本3.10以上 Centos6.5以上系统、64位系统、内核版本2.6.32以上
  • Centos必须能够联网

如何查看Liunx系统内核?

  • Centos7.x查看方法
    1
    uname -r
  • Centos6.x查看方法
    1
    2
    3
    lsb_release -a

    cat /etc/redhat-release

如果满足了上面的条件、我们现在就开始吧!

Docker概念

docker主机(Host):安装了Docker程序的机器(Docker直接安装在操作系统之上);
docker客户端(Client):连接docker主机进行操作;
docker仓库(Registry):用来保存各种打包好的软件镜像;
docker镜像(Images):软件打包好的镜像;放在docker仓库中;
docker容器(Container):镜像启动后的实例称为一个容器;容器是独立运行的一个或一组应用;

安装 Docker

Centos7.x安装

  1. 需要提前安装的必备组件: gcc gcc-c++ (如果安装了可以忽略)

    1
    2
    yum -y install gcc
    yum -y install gcc-c++
  2. 卸载旧版本Docker (如果没有安装可以忽略)

    1
    yum -y remove docker docker-common docker-selinux docker-engine
  3. 安装需要的软件包

    1
    yum install -y yum-utils device-mapper-peristent-data lvm2 

    如果yum被其他进程占用、 ps -ef|grep yum 查看占用进程 kill -9 占用的端口号 就可以了。

  4. 设置镜像仓库地址

    1
    yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  5. 更新yum软件包索引

    1
    yum makecache fast
  6. 安装Docker CE

    1
    yum -y install docker-ce
  7. 启动Docker

    1
    2
    systemctl start docker //启动Docker
    systemctl status docker //查看启动状态
  8. 其他

    1
    2
    3
    4
    5
    6
    7
    docker version //查看版本
    docker run hello-world //运行helloworld镜像(没有会从远程仓库pull)

    卸载
    systemctl stop docker
    yum -y remove docker-re
    rm -rf /var/lib/docker

Centos6.8安装

  1. yum install -y epel-release

    1
    Docker使用EPEL发布,RHEL系的OS首先要确保已经持有EPEL仓库,否则先检查OS的版本,然后安装相应的EPEL包。
  2. yum install -y docker-io

  3. 安装后的配置文件: /etc/sysconfig/docker

  4. 启动Docker后台服务: service docker start

  5. docker version验证

配置镜像加速

使用阿里云镜像加速(https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)

1
2
3
4
5
6
7
8
9
10
mkdir -p /etc/docker //创建多级目录
vim /etc/docker/daemon.json //编辑镜像地址

输入:
{
"registry-mirrors": ["粘贴你的镜像加速地址"]
}

systemctl daemon-reload //刷新配置
systemctl restart docker //重启Docker

Docker常用命令

帮助命令

  1. docker version //Docker版本

  2. docker info //Docker详细信息

  3. docker help //Docker命令信息

镜像命令

  1. docker images //列出本地主机上的镜像

    REPOSITORYTAGIMAGE IDCREATEDSIZE
    表示镜像的仓库源镜像的标签镜像ID镜像创建时间镜像大小

    可加参数:

    参数说明
    -a列出本地所有的镜像(含中间映像层)
    -q只显示镜像ID
    --digests只显示镜像的摘要信息
    --no-trunc显示完整的镜像信息
  2. docker search 镜像名字 //从云端查询指定镜像

    NAMEDESCRIPTIONOFFICIALSTARTSAUTOMATED
    镜像仓库源的名称镜像的描述是否 docker 官方发布类似 Github 里面的 star,表示点赞、喜欢的意思自动构建

    官网:https://hub.docker.com/

    可加参数:

    参数说明
    --no-trunc显示完整的镜像描述
    -s 数字列出收藏数不小于指定值的镜像)
    --automated只列出 automated bulid 类型的镜像
  3. docker pull 镜像名字[:TAG] //从云端下载指定镜像

  4. docker rmi 镜像ID //删除本地指定镜像

    可加参数:

    参数说明
    -f强制删除某个镜像 例:docker rmi -f fce289e99eb9
    -f 镜像名1:TAG 镜像名2:TAG强制删除多个镜像 例:docker rmi -f hello-world tomcat
    -f $(docker images -qa)强制删除所有本地镜像

容器命令

  1. docker run [OPTIONS] IMAGE [COMMAND] [ARG…] //新建并启动容器

    参数说明
    --name="容器新名字"为容器指定一个名字
    -d后台运行容器,并返回容器ID,也启动守护式容器
    -i以交互模式运行容器,通常与 -t 同时运行
    -t为容器重新分配一个伪输入终端,通常与 -i 同时运行
    -P随机端口映射
    -p指定端口映射,有以下四种格式:
    ip:hostPort:containerPort
    ip::containerPort
    hostPort:containerPort 主机端口:容器端口
    containerPort
  2. docker ps [OPTIONS] //列出当前所有正在运行的容器

    参数说明
    -a列出当前所有正在运行的容器+历史上运行过的
    -l显示最近创建的容器
    -n显示最近n个创建的容器 例:docker ps -n 3
    -q静默模式,只显示容器编号
    --no-trunc随机端口映射
  3. 退出容器

    参数说明
    exit容器停止退出
    Ctrl+P+Q容器不停止退出
  4. docker start 容器ID或者容器名 //启动容器

  5. docker restart 容器ID或者容器名 //重启容器

  6. docker stop 容器ID或者容器名 //停止容器

  7. docker kill 容器ID或者容器名 //强制停止容器

  8. docker rm 容器ID //删除已经停止容器

    参数说明
    docker rm -f $(docker ps -a -q)一次性删除多个容器
    docker ps -a -q|xargs docker rm容器不停止退出
  9. docker commit 提交容器副本使之成为一个新的镜像

    1
    docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名[:标签名]
    参数说明
    -a提交的镜像作者
    -c使用Dockerfile指令来创建镜像
    -m提交时的说明文字
    -p在commit时,将容器暂停
  10. docker inspect 镜像ID //获取容器/镜像的元数据、返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。

    参数说明
    -f指定返回值的模板文件
    -s显示总的文件大小
    --type为指定类型返回JSON

注意

  1. 启动守护式容器

    docker run -d 容器名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    使用镜像centos:latest以后台模式启动一个容器

    docker run -d centos

    问题:然后docker ps -a进行查看,会发现容器已经退出

    很重要的要说明的一点:Docker容器后台运行就必须有一个前台进程

    容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
    1
    2
    docker run -d centos /bin/sh -C "while true;do echo hello zykj;sleep 2;done"
    启动时给centos一些参数、可以让容器不停止运行、死循环输出日志
  2. 查看容器日志

    • docker logs -f -t –tail 容器ID

      参数说明
      -t是加入时间戳
      -f跟随最新的日志打印
      --tail数字显示最后多少条
  3. 查看容器内运行的进程

    1
    docker top 容器ID 
  4. 进入正在运行的容器以命令行交互

    • docker exec -it 容器ID bashShell //不进入容器里执行容器命令

      1
      2
      3
      4
      以Centos为例:
      docker exec -it 容器ID ls -l /tmp

      docker exec -it 容器ID /bin/bash //进入交互模式
    • 重新进入docker attach 容器ID

    区别:

    exec: 是在容器中打开新的终端,并且可以启动新的进程
    attach: 直接进入容器启动命令的终端,不会启动新的进程

  5. 从容器内拷贝文件到主机上

    1
    docker cp 容器ID:容器内路径目的主机路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
attach    Attach to a running container                 # 当前 shell 下 attach 连接指定运行镜像
build Build an image from a Dockerfile # 通过 Dockerfile 定制镜像
commit Create a new image from a container changes # 提交当前容器为新的镜像
cp Copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中
create Create a new container # 创建一个新的容器,同 run,但不启动容器
diff Inspect changes on a container's filesystem # 查看 docker 容器变化
events Get real time events from the server # 从 docker 服务获取容器实时事件
exec Run a command in an existing container # 在已存在的容器上运行命令
export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
history Show the history of an image # 展示一个镜像形成历史
images List images # 列出系统当前镜像
import Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on a container # 查看容器详细信息
kill Kill a running container # kill 指定 docker 容器
load Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save]
login Register or Login to the docker registry server # 注册或者登陆一个 docker 源服务器
logout Log out from a Docker registry server # 从当前 Docker registry 退出
logs Fetch the logs of a container # 输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口
pause Pause all processes within a container # 暂停容器
ps List containers # 列出容器列表
pull Pull an image or a repository from the docker registry server # 从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器
restart Restart a running container # 重启运行的容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save an image to a tar archive # 保存一个镜像为一个 tar 包[对应 load]
search Search for an image on the Docker Hub # 在 docker hub 中搜索镜像
start Start a stopped containers # 启动容器
stop Stop a running containers # 停止容器
tag Tag an image into a repository # 给源中镜像打标签
top Lookup the running processes of a container # 查看容器中运行的进程信息
unpause Unpause a paused container # 取消暂停容器
version Show the docker version information # 查看 docker 版本号
wait Block until a container stops, then print its exit code # 截取容器停止时的退出状态值

Docker容器数据卷

docker的理念将运行的环境打包形成容器运行,运行可以伴随容器,但是我们对数据的要求是希望持久化,容器之间可以共享数据,Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为容器的一部分保存下来,那么当容器被删除之后,数据也就没了,为了能够保存数据,在docker容器中使用卷。卷就是目录或者文件,存在于一个或者多个容器中,但是不属于联合文件系统,因此能够绕过Union File System提供一些用于持久化数据或共享数据的特点。
关键字: 容器的持久化容器间继承+共享数据

数据卷

容器内添加

直接命令添加
  • 命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

    例:(ps:目录不存在会自动创建)
    docker run -it -v /myDataVolume:/dataVolumeContianer centos

    通过docker inspect查看
    "VolimesRW":{
    "/dataVolumeContainer": true
    },

    Docker挂载主机目录Docker访问出现cannot open directory : Permission denied
    解决办法:在挂载目录后多加一个--privileged=true参数即可
  • 容器和宿主机之间会数据共享

  • 容器停止退出后,主机修改后数据同样数据同步

  • 命令(带权限:主机目录创建文件、容器目录只读)

    1
    2
    3
    4
    5
    6
    docker run -it -v /宿主机绝对路径目录:/容器内目录:ro镜像名

    通过docker inspect查看
    "VolimesRW":{
    "/dataVolumeContainer": false
    },
Dockerfile添加
  • 根目录(其他目录也可以)下新建mydocker文件夹并进入
    1
    2
    cd /
    mkdir mydocker
  • 可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷
    1
    2
    3
    4
    5
    VOLUME["/dataVolumeContainer","/dataVolumeContainer2","/dataVolumeContainer3"]

    说明:
    出于可移植和分享的考虑,用 -v主机目录:容器目录这种方法不能够直接在Dockerfile中实现。
    由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
  • File构建
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    vim Dockerfile

    # volume test
    FROM centos
    VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
    CMD echo "Hello,-----world!"
    CMD /bin/bash

    通过docker命令解释就是:
    docker run -it -V /host1: /dataVolumeContainer1 -v /host2:/dataVolumeContainer2 centos /bin/bash
  • build后生成镜像 获得一个新镜像zykj/centos
    1
    2
    3
    4
    5
    docker build -f /mydocker/Dockerfile -t zykj/centos .

    -f :指定要使用的Dockerfile路径;
    --tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
    . :当前目录
  • run容器

数据卷容器

命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器

容器间数据共享 - -volumes-from

  • 命令

    1
    docker run -it --name 子容器 --volumes-from 父容器 zykj/centos
  • 结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止

DockerFile

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

构建三个步骤

  • 编写Dockerfile文件
  • docker build
  • docker run

Dockerfile构建过程解析

Dockerfile内容基础知识

1
2
3
4
每条保留字指令都必须为大写字母且后面要跟随至少一个参数
指令按照从上到下,顺序执行
#表示注释
每条指令都会创建一一个新的镜像层,并对镜像进行提交

Docker执行Dockerfile的大致流程

1
2
3
4
5
docker从基础镜像运行一个容器
执行一条指令并对容器作出修改
执行类似docker commit的操作提交-一个新的镜像层
docker再基于刚提交的镜像运行一个新容器
执行dockerfile中的下一条指令直到所有指令都执行完成

总结:

1
2
3
4
5
Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉 及的内容包括执行代码或者是文件、环境
变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,
这时需要考虑如何设计namespace的权限控制)等等;
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行Docker镜像时,会真正开始提供服务;
Docker容器,容器是直接提供服务的。

Docker体系结构(保留字指令)

  • FROM 基础镜像,当前新镜像是基于哪个镜像的

  • MAINTAINER 镜像维护者的姓名和邮箱地址

  • RUN 容器构建时需要运行的命令

  • EXPOSE 当前容器对外暴露出的端口

  • WORKDIR 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点(就是工作目录)

  • ENV 用来在构建镜像过程中设置环境变量

    1
    2
    3
    4
    5
    6
    ENV MY_PATH /usr/mytest

    这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
    也可以在其它指令中直接使用这些环境变量

    比如: WORKDIR $MY_PATH
  • ADD 将宿主机目录下的文件拷贝进镜像且ADD命令会 自动处理URL解压tar压缩包,类似ADD,拷贝文件和目录到镜像中。

  • COPY 将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置

    1
    2
    3
    两种方法:
    COPY src dest
    COPY ["src","dest"]
  • VOLUME 容器数据卷, 用于数据保存和持久化工作

  • CMD

    • Dockerfile中可以有多个CMD指令,但只有最后一个生效CMD 会被docker run之后的参数替换

      1
      2
      3
      4
      5
      6
      CMD容器启动命令
      CMD指令的格式和RUN相似,也是两种格式:

      ● shell格式: CMD <命令>
      ● exec格式: CMD ["可执行文件","参数1", "参数2" ...]
      ● 参数列表格式: CMD ["参数1","参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
    • 指定一个容器启动时要运行的命令口

  • ENTRYPOINT

    • 指定一个容器启动时要运行的命令
    • ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数
  • ONBUILD 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发

案例

Base镜像(scratch)

DockerHub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的

1
2
docker pull centos
docker run -it centos /bin/bash

自定义镜像mycentos

  • 编写
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    vim Dockerfile

    FROM centos
    MAINTAINER zykj<zykj@zykj.com>

    ENV MYPATH /usr/local
    WORKDIR $MYPATH

    RUN yum -y install vim
    RUN yum -y install net-tools

    EXPOSE 80

    CMD echo $MYPATH
    CMD echo "success-------------ok"
    CMD /bin/bash
  • 构建
    1
    2
    3
    docker build 镜像名字:TAG .

    例:docker build -f /mydocker/Dockerfile mycentos:1.3 .
  • 运行
    1
    docker run -it 镜像名字:TAG
  • 列出镜像的变更历史
    1
    docker history 镜像ID

CMD/ENTRYPOINT案例

  • 都是指定一个容器启动时要运行的命令
  • CMD
    • Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
    • 运行tomcat docker run -it -p 8888:8080 tomcat ls -l
  • ENTRYPOINT
    • docker run之后的参数会被当做参数传递给ENTRYPOINT,之后形成新的命令组合
    • 例子
      • 制作 CMD 版可以查询IP信息的容器(curl直接访问http://ip.cn会报403、所以。。。以下告诉方法)
        1
        2
        3
        FROM centos
        RUN yum install -y curl
        CMD [ "curl" , "-s" , "http://ip.cn" ]
        curl命令解释
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        curl命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。
        如果系统没有curl可以使用yum install curl安装,也可以下载安装。
        curl是将下载文件输出到stdout

        使用命令: curl http://www.baidu.com
        执行后,www.baidu.com的html就会显示在屏幕上了

        这是最简单的使用方法。用这个命令获得了http://curl.haxx.se指向的页面,同样,如果这里的URL指向的是一个文件
        或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将只显示文件头部,即HTML文档的
        header。要全部显示,请加参数 -i
      • 问题 如果我们希望显示HTTP头信息,就需要加上i参数、docker run myip -i 但是会报错
      • WHY
        1
        2
        3
        4
        5
        6
        7
        我们可以看到可执行文件找不到的报错,executable file not found。 
        之前我们说过,跟在镜像名后面的是command,运行时会替换CMD的默认值。
        因此这里的-i替换了原来的CMD,而不是添加在原来的curl -s htp://ip.cn 后面。而-i根本不是命令,所以自然找不到。

        那么如果我们希望加入-i这参数,我们就必须重新完整的输入这个命令:

        docker run myip curl -s http://ip.cn -i
      • 制作 ENTROYPOINT 版查询IP信息的容器
        1
        2
        3
        FROM centos
        RUN yum install -y curl
        ENTROYPOINT [ "curl" , "-s" , "http://ip.cn" ]
        通过使用ENTROYPOINT可以执行docker run myip -i、-i作为参数追加

自定义Tomcat9镜像

  1. mkdir -p /zykjuse/mydockerfile/tomcat9

  2. 在上述目录下 touch c.txt

  3. jdktomcat 安装的压缩包拷贝进上一步目录

    apache-tomcat-9.0.8.tar.gz
    jdk-8u171-linux-x64.tar.gz

  4. 在/zzkjuse/mydockerfile/tomcat9目录下新建Dockerfile文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    FROM centos
    MAINTAINER zykj<zykj@zykj.com>
    #把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
    COPY c.txt /usr/local/cincontainer.txt
    #把java与tomcat添加到容器中
    ADD jdk-8u171-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.8.tar.gz /usr/local/
    #安装vim编辑器
    RUN yum -y install vim
    #设置工作访问时候的WORKDIR路径,登录落脚点
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    #配置java与tomcat环境变量
    ENV JAVA_HOME /usr/local/jdk1.8.0_171
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
    ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    #容器运行时监听的端口
    EXPOSE 8080
    #启动时运行tomcat
    # ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ]
    # CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
    CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out
  5. 构建

    1
    2
    docker build -t zykjtomcat9 .
    ps:如果Dockerfile在当前目录内可以不指定
  6. 运行

    1
    docker run -d -p 9080:8080 --name myt9 -v /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test -v /zzyyuse/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true zykjtomcat9
  7. 结合前述容器卷将测试的web服务test发布

    • 在/zykjuse/mydockerfile/tomcat9下创建test目录

      1
      mkdir test
    • 编写 a.jsp

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      vim a.jsp

      <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
      <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      <html>
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Insert title here</title>
      </head>
      <body>
      -----------welcome------------
      <%="i am in docker tomcat self "%>
      <br>
      <br>
      <% System.out.println("=============docker tomcat self");%>
      </body>
      </html>
    • 在当前创建WEB-INF目录

      1
      mkdir WEB-INF
    • 编写web.xml

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      vim web.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://java.sun.com/xml/ns/javaee"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
      id="WebApp_ID" version="2.5">

      <display-name>test</display-name>

      </web-app>

      最后重启容器访问 localhost:9080/test/a.jsp就可以了

      小总结

安装软件

安装Tomcat

  1. docker hub上面查找tomcat镜像(docker search tomcat)
  2. 从docker hub上拉取tomcat镜像到本地(docker pull tomcat)
  3. docker images查看是否有拉取到的tomcat
  4. 使用tomcat镜像创建容器(也叫运行镜像) (docker run -it -p 8080:8080 tomcat)
    • -p : 主机端口:docker容器端口
    • -P : 随机分配端口D
    • -i : 交互
    • -t : 终端

安装MySQL

  1. docker hub上面查找mysql镜像
  2. 从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.7
  3. 使用mysql5.7镜像创建容器(也叫运行镜像)
    • 使用mysql镜像
      1
      docker run -p 3306:3306 --name mysql -v /zykjuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs -v /zykjuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
      命令说明:
      1
      2
      3
      4
      5
      6
      7
      -p 3306:3306:将主机的3306端口映射到docker容器的3306端口。
      --name mysql:运行服务名字
      -v /zykjuse/mysql/conf:/etc/mysql/conf.d :将主机/zykjuse/mysql目录下的conf/my.cnf 挂载到容器的 /etc/mysql/conf.d
      -v /zykjuse/mysql/logs:/logs:将主机/zykjuse/mysql目录下的 logs 目录挂载到容器的 /logs。
      -v /zykjuse/mysql/data:/var/lib/mysql :将主机/zykjuse/mysql目录下的data目录挂载到容器的 /var/lib/mysql
      -e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
      -d mysql:5.7 : 后台程序运行mysql5.7
      1
      docker exec -it MySQL运行成功后的容器ID  /bin/bash
    • 外部Win10也来连接运行在docker上的mysql服务
    • 数据备份小测试(可以不做)
      1
      docker exec mysql服务容器ID sh -c ' exec mysqldump --all-databases -uroot -p"123456" ' > /zykjuse/all-databases.sql

安装Redis

  1. 从docker hub.上(阿里云加速器)拉取redis镜像到本地标签为3.2

  2. 使用redis3. 2镜像创建容器(也叫运行镜像)

    • 使用镜像

      1
      docker run -p 6379:6379 -v /zykjuse/myredis/data:/data -v /zykjuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf  -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes

      命令说明:

      1
      2
      3
      4
      5
      -p 6379:6379:将主机的6379端口映射到docker容器的3306端口。
      -v /zykjuse/myredis/data:/data:将主机/zykjuse/myredis目录下的 data 目录挂载到容器的 /data。
      -v /zykjuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf:将主机/zykjuse/myredis/conf/目录下的 redis.conf 目录 挂载到容器的 /usr/local/etc/redis/redis.conf
      -d redis:3.2 redis-server: 后台程序运行redis:3.2、redis-server
      --appendonly yes:开启AOF模式
    • 在主机 /zykjuse/myredis/conf/redis.conf 目录下新建redis.conf文件

      1
      vim /zzyuse/myredis/conf/redis.conf/redis.conf

      redis.conf 在这里可以复制 https://github.com/antirez/redis/blob/unstable/redis.conf

    • 测试redis cli连接上来

      1
      docker exec -it 运行着Rediis服务的容器ID redis-cli
    • 测试持久化文件生成

其他

IDEA整合Docker部署java项目

配置Docker的远程访问

  1. 修改/lib/systemd/system/docker.service

    1
    vim /lib/systemd/system/docker.service
  2. 替换ExecStart

    1
    2
    3
    4
    替换
    ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

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

  3. 重启Docker服务

    1
    2
    systemctl daemon-reload
    systemctl restart docker
  4. 查看2375端口是否被监听

    1
    netstat -nlpt

  5. 服务器防火墙开启2375端口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 开放2375端口
    firewall-cmd --add-port=2375/tcp --permanent
    # 重启防火墙(修改配置后要重启防火墙)
    firewall-cmd --reload
    # 查看开放的端口
    firewall-cmd --zone=public --list-ports

    # 参数解释
    firwall-cmd:是Linux提供的操作firewall的一个工具;
    --permanent:表示设置为持久;
    --add-port:标识添加的端口;

    如果是云服务器、那么还要添加安全组规则(这里以阿里云服务器为演示)

  6. 验证是否成功

    1
    2
    3
    4
    本地:
    curl http://127.0.0.1:2375/version
    网页:
    http://服务器IP:2375/version


    网页访问一样。

IDEA中配置Docker插件

  • 确保IDEA安装Docker插件

  • 打开设置Settings->Build,Execution,Deployment、找到Docker添加

配置好了会显示Connection successful

接下来配置镜像加速

点击OK之后,下方控制栏,出现Docker控制台

集成Maven插件

  • 在项目的pom.xml文件中添加以下内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <properties>
    <!--docker镜像的前缀-->
    <docker.image.prefix>docker</docker.image.prefix>
    </properties>


    <plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.0.0</version>

    <configuration>
    <!--远程Docker的地址-->
    <dockerHost>http://localhost:2375</dockerHost>
    <!--镜像名称,前缀/项目名-->
    <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
    <!--指定标签-->
    <imageTags>
    <imageTag>latest</imageTag>
    </imageTags>

    <!-- 指定 Dockerfile 路径 ${project.basedir}:项目根路径下-->
    <dockerDirectory>src/main/docker</dockerDirectory>
    <!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
    <resources>
    <resource>
    <targetPath>/</targetPath>
    <!--jar 包所在的路径 此处配置的 即对应 target 目录-->
    <directory>${project.build.directory}</directory>
    <!-- 需要包含的 jar包 ,这里对应的是 Dockerfile中添加的文件名 -->
    <include>${project.build.finalName}.jar</include>
    </resource>
    </resources>
    </configuration>
    </plugin>
  • 根据配置的 <dockerDirectory>src/main/docker</dockerDirectory>srcmain创建docker目录、编写Dockerfile
1
2
3
4
5
6
7
FROM java:8

VOLUME /tmp

ADD *.jar app.jar

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
  • Maven生成jar包

确保 target 目录下有生成的jar包

  • Maven构建镜像

  • 运行Docker镜像

然而、这样就行了吗?

当然不行的,前面提到的配置是允许所有人都可以访问的,因为docker默认是root权限的,你把2375端口暴露在外面,意味着别人随时都可以提取到你服务器的root权限,是很容易被黑客黑的

我们需要继续配置

Docker CA认证

  • 创建ca文件夹,用于存放CA私钥和公钥

    1
    2
    mkdir -p /usr/local/ca
    cd /usr/local/ca/
  • 创建密码(需要连续输入两次相同的密码)

    1
    openssl genrsa -aes256 -out ca-key.pem 4096
  • 依次输入密码、国家、省、市、组织名称等(随便输入、影响不大)

    1
    openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
  • 生成 server-key.pem

    1
    openssl genrsa -out server-key.pem 4096
  • 把下面的 $Host 换成你自己服务器外网的IP或者域名

    1
    2
    3
    4
    5
    openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

    例子:
    openssl req -subj "/CN=192.168.1.106" -sha256 -new -key server-key.pem -out server.csr
    openssl req -subj "/CN=www.baidu.com" -sha256 -new -key server-key.pem -out server.csr
  • 配置白名单

    配置要允许那些ip可以连接到服务器的docker,因为已经是ssl连接,所以我推荐配置0.0.0.0,也就是所有ip都可以连接(但只有拥有证书的才可以连接成功),这样配置好之后公司其他人也可以使用。如果你不想这样,那你可以配置ip,用逗号分隔开。下面的$Host依旧是你服务器外网的IP或者域名,请自行替换。

    1
    2
    3
    填写的是ip地址的话命令如下echo subjectAltName = IP:$HOST,IP:0.0.0.0 >> extfile.cnf

    填写的是域名的话命令如下 echo subjectAltName = DNS:$HOST,IP:0.0.0.0 >> extfile.cnf
  • 执行命令,将Docker守护程序密钥的扩展使用属性设置为仅用于服务器身份验证

    1
    echo extendedKeyUsage = serverAuth >> extfile.cnf
  • 执行命令,并输入之前设置的密码,生成签名证书

    1
    openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \-CAcreateserial -out server-cert.pem -extfile extfile.cnf
  • 生成客户端的key.pem,到时候把生成好的几个公钥私钥拷出去即可

    1
    openssl genrsa -out key.pem 4096
  • 执行命令

    1
    openssl req -subj '/CN=client' -new -key key.pem -out client.csr
  • 执行命令,要使密钥适合客户端身份验证,请创建扩展配置文件

    1
    echo extendedKeyUsage = clientAuth >> extfile.cnf
  • 生成 cert.pem ,需要输入前面设置的密码,生成签名证书

    1
    openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \-CAcreateserial -out cert.pem -extfile extfile.cnf
  • 删除不需要的文件,两个证书签名请求

    1
    rm -v client.csr server.csr
  • 修改权限,要保护您的密钥免受意外损坏,请删除其写入权限。要使它们只能被您读取,更改文件模式

    1
    chmod -v 0400 ca-key.pem key.pem server-key.pem
  • 证书可以是对外可读的,删除写入权限以防止意外损坏

    1
    chmod -v 0444 ca.pem server-cert.pem cert.pem
  • 归集服务器证书

    1
    2
    3
    cp server-*.pem  /etc/docker/

    cp ca.pem /etc/docker/
  • 修改Docker配置,使Docker守护程序仅接受来自提供CA信任的证书的客户端的连接

    1
    vim /lib/systemd/system/docker.service
  • ExecStart=/usr/bin/dockerd 替换

    1
    ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server-cert.pem --tlskey=/etc/docker/server-key.pem -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
  • 重新加载daemon并重启docker

    1
    2
    systemctl daemon-reload 
    systemctl restart docker
  • 重启docker

    1
    service docker restart
  • 复制这几个文件到本地

  • 回到IDEA

    • 重新配置pom文件

      1
      2
      <!--CA存放路径-->
      <dockerCertPath>D:\ca</dockerCertPath>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      <properties>
      <!--docker镜像的前缀-->
      <docker.image.prefix>docker</docker.image.prefix>
      </properties>


      <plugin>
      <groupId>com.spotify</groupId>
      <artifactId>docker-maven-plugin</artifactId>
      <version>1.0.0</version>

      <configuration>
      <!--远程Docker的地址-->
      <dockerHost>http://localhost:2375</dockerHost>
      <!--CA存放路径-->
      <dockerCertPath>D:\ca</dockerCertPath>
      <!--镜像名称,前缀/项目名-->
      <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
      <!--指定标签-->
      <imageTags>
      <imageTag>latest</imageTag>
      </imageTags>

      <!-- 指定 Dockerfile 路径 ${project.basedir}:项目根路径下-->
      <dockerDirectory>src/main/docker</dockerDirectory>
      <!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
      <resources>
      <resource>
      <targetPath>/</targetPath>
      <!--jar 包所在的路径 此处配置的 即对应 target 目录-->
      <directory>${project.build.directory}</directory>
      <!-- 需要包含的 jar包 ,这里对应的是 Dockerfile中添加的文件名 -->
      <include>${project.build.finalName}.jar</include>
      </resource>
      </resources>
      </configuration>
      </plugin>

      最后重新生成jar包、重新构建docker镜像就可以了。

参考连接: