51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Docker

Docker安装 {#Docker安装}

卸载 {#卸载}

如果之前有安装过旧版本的Docker,则通过命令卸载旧版本的Docker

|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 | 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 |

没有任何匹配,说明没装过docker

安装 {#安装}

首先需要虚拟机联网,安装yum工具

|---------------|---------------------------------------------------------------------------------------| | 1 2 3 | yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 --skip-broken |

运行耐心等待一下,安装完成(最后显示 完毕!)

然后更新本地镜像源:配置阿里云的仓库

|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 | # 设置docker镜像源 yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo yum makecache fast |

安装docker

|-----------|----------------------------------| | 1 | yum install -y docker-ce |

docker-ce: 社区版

启动Docker {#启动Docker}

防火墙设置

|---------------------|----------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | # 关闭 systemctl stop firewalld # 禁止开机启动防火墙 systemctl disable firewalld # 可以查看防火墙状态 systemctl status firewalld |

启动

|-------------------|-------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | systemctl start docker # 启动docker服务 systemctl stop docker # 停止docker服务 systemctl restart docker # 重启docker服务 |

查看docker状态

|-----------|---------------------------------| | 1 | systemctl status docker |

查看docker版本

|-----------|-------------------| | 1 | docker -v |

配置镜像加速 {#配置镜像加速}

docker官方镜像仓库网速较差,我们需要设置国内镜像服务:
参考阿里云的镜像加速文档: https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 | sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<- 'EOF' { "registry-mirrors" : [ "https://gtxivg4h.mirror.aliyuncs.com" ] } EOF sudo systemctl daemon-reload sudo systemctl restart docker |

部署MySQL {#部署MySQL}

先停掉虚拟机中的MySQL,确保虚拟机已经安装Docker,且网络开通的情况下,执行下面命令即可安装MySQL

|---------------------|-------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | docker run -d \ --name mysql \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql |

解读:

docker run -d :创建并运行一个容器,**-d**则是让容器以后台进程运行

--name mysql : 给容器起个名字叫mysql,必须唯一

-p 3306:3306 : 设置端口映射。(后面这个是容器内MySQL默认端口,前面是映射出去的端口(宿主机),比如3307)

容器是隔离环境,外界不可访问。但是可以将宿主机端口映射容器内到端口,当访问宿主机指定端口时,就是在访问容器内的端口了。

容器内端口往往是由容器内的进程决定,例如MySQL进程默认端口是3306,因此容器内端口一定是3306;而宿主机端口则可以任意指定,一般与容器内保持一致。

格式: -p 宿主机端口:容器内端口,示例中就是将宿主机的3306映射到容器内的3306端口

-e TZ=Asia/Shanghai : 配置容器内进程运行时的一些参数(e-->environment)

格式:**-e KEY=VALUE**,KEY和VALUE都由容器内进程决定

案例中,TZ=Asia/Shanghai是设置时区;MYSQL_ROOT_PASSWORD=123456是设置MySQL默认密码

mysql : 设置镜像名称,Docker会根据这个名字搜索并下载镜像

格式:REPOSITORY:TAG,例如mysql:8.0,其中REPOSITORY可以理解为镜像名,TAG是版本号

在未指定TAG的情况下,默认是最新版本,也就是mysql:latest

连接远程数据库 {#连接远程数据库}

打开数据库连接工具

如果出现 没有权限 ,则在Docker容器中,输入指令, 进入容器,查看容器内目录

|-----------|--------------------------------------------------| | 1 | docker exec -it container_name /bin/bash |

登录MySQL

|-----------|--------------------------| | 1 | mysql -u root -p |

修改权限

|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; # 更新user为root,host为% 的密码为123456 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456'; # 更新user为root,host为localhost 的密码为123456 |

刷新权限

|-----------|---------------------------------| | 1 | FLUSH PRIVILEGES; #刷新权限 |

最后查询用户信息 (查看root用户)

|-----------|------------------------------------------------------------------------| | 1 | select host,user,plugin,authentication_string from mysql.user; |

连接成功则可以像在Windows操作本地数据库一样的了

Docker基础 {#Docker基础}

常见命令 {#常见命令}

| 命令 | 说明 | |----------------|---------------------| | docker pull | 拉取镜像 | | docker push | 推送镜像到DockerRegistry | | docker images | 查看本地镜像 | | docker rmi | 删除本地镜像 | | docker run | 创建并运行容器(不能重复创建) | | docker stop | 停止指定容器 | | docker start | 启动指定容器 | | docker restart | 重新启动容器 | | docker rm | 删除指定容器 | | docker ps | 查看容器 | | docker logs | 查看容器运行日志 | | docker exec | 进入容器 | | docker save | 保存镜像到本地压缩文件 | | docker load | 加载本地压缩文件到镜像 | | docker inspect | 查看容器详细信息 | | docker stats | 查看容器资源使用情况(通过容器id) |

Docker文档 Docker Docs

案例 {#案例}

以拉取Nginx为例:

需求:

  • 在DockerHub中搜索Nginx镜像,查看镜像的名称
  • 拉取Nginx镜像
  • 查看本地镜像列表
  • 创建并运行Nginx容器
  • 查看容器
  • 停止容器
  • 再次启动容器
  • 进入Nginx容器
  • 删除容器

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # 1.访问Docker Hub搜索镜像 # 2.拉取Nginx镜像,不指定版本即默认为latest最新 docker pull nginx # 3.查看本地镜像列表 docker images # 结果如下 [root@localhost ~] # docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 22 months ago 141MB mysql latest 3218b38490ce 22 months ago 516MB # 4.创建并运行Nginx容器 docker run -d --name nginx -p 80:80 nginx # 5.查看容器 docker ps # 5.1查看容器格式化(格式会更加清爽) docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" # 结果 [root@localhost ~] # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b83c1bfa9956 nginx "/docker-entrypoint...." 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp nginx [root@localhost ~] # docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" CONTAINER ID IMAGE PORTS STATUS NAMES b83c1bfa9956 nginx 0.0.0.0:80->80/tcp, :::80->80/tcp Up 2 minutes nginx # 6.停止容器 docker stop nginx # 6.1查看所有容器 docker ps -a docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" # 结果:(刚刚停止的Nginx的状态为Exited) [root@localhost ~] # docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}" CONTAINER ID IMAGE PORTS STATUS NAMES b83c1bfa9956 nginx Exited (0) 3 minutes ago nginx 107a163cba71 mysql 3306/tcp, 33060/tcp Created xenodochial_allen b32527ef7193 mysql Exited (0) 25 hours ago mysql # 7.启动容器 docker start nginx # 8.进入容器,查看容器内目录 docker exec -it nginx bash # ecec:执行 -it:模拟可输入终端 bash:命令行交互 # 9.查看日志 docker logs nginx # 查看nginx日志 docker logs -f nginx # 一直查看Nginx日志 # 10.退出容器 exit # 11.删除容器 docker rm nginx # 在运行的容器删除会提示 # 无法删除,则需要先停止(stop在rm),或者 docker rm -f nginx |

命令别名 {#命令别名}

比如在前面的案例中,我们需要对docker ps显示的内容进行格式化(format),指令过长,每一次都要输入这么多, 非常麻烦

|---------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 修改/root/.bashrc文件 vi /root/.bashrc 内容如下: # .bashrc # User specific aliases and functions alias rm = 'rm -i' alias cp = 'cp -i' alias mv = 'mv -i' alias dps= 'docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"' alias dis= 'docker images' # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi |

然后,执行命令使别名生效:

|-----------|------------------------------| | 1 | source /root/.bashrc |

所以当我们设置了这个, 如果需要查看镜像的情况, 则可以使用dps格式化别名指令

数据卷 {#数据卷}

容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,我们要读写容器内的文件非常不方便 (比如我们进入到容器中使用vi指令修改index.html会提示没有指令).

数据卷(volume) 是一个虚拟目录,是 容器内目录宿主机目录 之间映射的桥梁

以Nginx为例,众所周知

  • html: 放静态资源
  • conf: 放配置文件

如果我们要让Nginx代理我们的静态资源,最好是放到 html 目录;如果我们要修改Nginx的配置,最好是找到 conf 下的 nginx.conf 文件

但是非常遗憾的一点是, 不能直接去修改它(原容器), 容器运行的Nginx所有的文件都在容器内部。所以我们必须利用数据卷将两个目录与宿主机目录关联,方便我们操作。如图:

上图解答:

我们创建了两个数据卷html和conf

其中html对应nginx容器中的/html, 通过数据卷指向了宿主机中的文件/html, _data是用来存放数据自动创建的, 这样一来容器和宿主机就被 关联 起来了了, 称之为 挂载

这样我们就可以在宿主机中的 /var/lib/docker/volumes/html/_data 存放资源, 那么容器中的数据也会被容器相对应的目录所映射

当前操作为 双向绑定 , 宿主机自动映射到容器

/var/lib/docker/volumes目录为默认存放所有容器数据卷的目录, 在下根据数据卷的名称创建新目录, 例如: /数据卷名称/_data

数据卷命令 {#数据卷命令}

| 命令 | 说明 | |-----------------------|------------| | docker volume create | 创建数据卷 | | docker volume ls | 查看所有数据卷 | | docker volume rm | 删除指定数据卷 | | docker volume inspect | 查看某个数据卷的详情 | | docker volume prune | 清除数据卷 |

Docker文档 Docker Docs

注意: 容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且 创建容器的过程中,数据卷会自动创建

案例 {#案例-1}

需求;

  • 创建Nginx容器, 修改nginx容器内的html目录下的index.html文件内容
  • 将静态资源部署到nginx的html目录

提示: 在执行docker run 命令时, 使用 -v 数据卷:容器内目录 可以完成数据卷挂载

当创建容器时, 如果挂载了数据卷且数据卷不存在, 则会自动创建数据卷

|------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 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 38 39 40 41 42 | # 1.首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷 docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx # 2.然后查看数据卷 docker volume ls # 结果 [root@localhost ~] # docker volume ls DRIVER VOLUME NAME local a8bcfc131404273c3d5a5a450fbcc270dbf414d1367648190e864eebfc7802ad local html # 刚刚创建的卷在这 # 3.查看数据卷详情 docker volume inspect html # 结果 [root@localhost ~] # docker volume inspect html [ { "CreatedAt" : "2023-11-05T21:18:52+08:00" , "Driver" : "local" , "Labels" : null, "Mountpoint" : "/var/lib/docker/volumes/html/_data" , # 宿主机位置(映射) "Name" : "html" , "Options" : null, "Scope" : "local" } ] # 4.查看/var/lib/docker/volumes/html/_data目录 [root@localhost ~] # ll /var/lib/docker/volumes/html/_data 总用量 8 -rw-r--r--. 1 root root 497 12月 28 2021 50x.html -rw-r--r--. 1 root root 615 12月 28 2021 index.html # 5.进入该目录,并随意修改index.html内容 [root@localhost ~] # cd /var/lib/docker/volumes/html/_data #修改 [root@localhost _data] # vi index.html # 6.进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化 docker exec -it nginx bash cd /usr/share/nginx/html |

如果不指定挂载目录,自动会为你挂载到/usr/lib下

挂载本地目录或文件 {#挂载本地目录或文件}

数据卷的目录结构较深,如果我们去操作数据卷目录会不太方便。在很多情况下,我们会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:

|-----------------|-------------------------------------------------------| | 1 2 3 4 | # 挂载本地目录 -v 本地目录:容器内目录 # 挂载本地文件 -v 本地文件:容器内文件 |

注意: 本地目录或文件必须以 `/` 或 `./`开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。

|-------------|-------------------------------------------------------------------------------------------------------------------------------| | 1 2 | -v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷 -v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录 |

案例需求:

  • 挂载 /root/mysql/data 到容器内的 /var/lib/mysql 目录
  • 挂载 /root/mysql/init 到容器内的 /docker-entrypoint-initdb.d 目录(初始化的SQL脚本目录 ---> 只有第一次才生效)
  • 挂载 /root/mysql/conf 到容器内的 /etc/mysql/conf.d 目录(这个是MySQL配置文件目录)

解释: init为SQL脚本初始化, conf为配置文件, 其中配置文件主要是配置一些MySQL默认编码, utf8mb4

我们在虚拟机创建对应的目录,data, init, conf

本地目录挂载:(关于MySQL的挂载详情直达 MySQL Image | Docker Hub )

|---------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 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 38 39 40 41 | # 1.删除原来的MySQL容器 docker rm -f mysql # 2.进入root目录(:需要设置挂载的目录,提前创建好挂载目录) cd ~ # 3.创建并运行新的MySQL容器,并且挂载(-v)到本地目录 # 当前使用的路径为全路径 /root/mysql, 也可以./root/mysql docker run -d \ --name mysql \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123456 \ -v /root/mysql/data:/var/lib/mysql \ -v /root/mysql/conf:/etc/mysql/conf.d \ -v /root/mysql/init:/docker-entrypoint-initdb.d \ mysql # 4.查看MySQL容器内数据 # 查看data目录,会发现里面有大量数据库数据,说明数据库完成了初始化 ls -l data # 4.1 进入MySQL docker exec -it mysql bash # 4.2 登录mysql # 4.3 查看编码表 show variables like "%char%" # 结果,发现编码是预设的utf8mb4没有问题 +--------------------------+--------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | utf8mb4 | | character_set_filesystem | binary | | character_set_results | utf8mb4 | | character_set_server | utf8mb4 | | character_set_system | utf8mb3 | | character_sets_dir | /usr/share/mysql-8.0/charsets/ | +--------------------------+--------------------------------+ # 5.查看数据(其实就是SQL语言了) |

镜像 {#镜像}

在这之前, 前面都是pull别人的镜像, 如果我也需要部署一个自己的镜像, 那么该怎么做呢?

镜像结构 {#镜像结构}

在构建镜像之前, 我们需要先了解镜像的结果.

镜像之所以可以让我们 快速 跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。

所以不容易看出, 自定义镜像的本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成

镜像是由 层级结构 组成: (在我们pull镜像的时候就不难看出)

Dockerfile {#Dockerfile}

Dockerfile就是一个文本文件, 其中包含了一个个的 指令(Instruction) , 用指令来说明要执行什么操作来构建镜像。将来Docker可以根据Dockerfile来帮我们构建镜像。常见指令如下:

| 指令 | 说明 | 示例 | |----------------|----------------------------|-----------------------------| | FROM | 指定基础镜像 | from centos:6 | | ENV | 设置环境变量,可在后面指令使用 | enu alue | | COPY | 拷贝本地文件到镜像的指定目录 | copy ./xx.jar /tmp/app.jar | | RUN | 执行Linux的shell命令,一般是安装过程的命令 | run yum install gcc | | EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | expose 8080 | | ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | entrypoint java -jar xx.jar |

更多详细语法, 请参考官方文档 Dockerfile reference | Docker Docs

例如需要基于Ubuntu构建一个Java应用, 其中Dockerfile内容如下

|---------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 指定基础镜像 FROM ubuntu:16.04 # 配置环境变量,JDK的安装目录、容器内时区 ENV JAVA_DIR=/usr/local ENV TZ=Asia/Shanghai # 拷贝jdk和java项目的包 COPY ./jdk8.tar.gz $JAVA_DIR / COPY ./docker-demo.jar /tmp/app.jar # 设定时区 RUN ln -snf /usr/share/zoneinfo/ $TZ /etc/localtime && echo $TZ > /etc/timezone # 安装JDK RUN cd $JAVA_DIR \ && tar -xf ./jdk8.tar.gz \ && mv ./jdk1.8.0_144 ./java8 # 配置环境变量 ENV JAVA_HOME= $JAVA_DIR /java8 ENV PATH= $PATH : $JAVA_HOME /bin # 指定项目监听的端口 EXPOSE 8080 # 入口,java项目的启动命令 ENTRYPOINT [ "java" , "-jar" , "/app.jar" ] |

对于JDK镜像配置, 我们可以使用别人提供的JDK基础镜像, 简化Dockerfile

|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 | # 基础镜像 FROM openjdk:11.0-jre-buster # 省去JDk配置 # 设定时区 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/ $TZ /etc/localtime && echo $TZ > /etc/timezone # 拷贝jar包 COPY docker-demo.jar /app.jar # 入口 ENTRYPOINT [ "java" , "-jar" , "/app.jar" ] |

最后相对于上面那个, 下面这个简洁了很多了

构建镜像 {#构建镜像}

当Dockerfile编写好之后, 就可以使用命令来构建镜像了, 例如在当前目录下准备好了一个 Dockerfile 文件和 ClickCount.jar 项目jar包

|-----------------|----------------------------------------------------------------------| | 1 2 3 4 | # 进入存放文件的目录 cd /root/demo # 开始构建 docker build -t click:1.0 . |

命令说明:

  • docker build : 构建一个docker镜像
  • -t :是给镜像起名, 格式一人撒repository:tag的格式, 如果不指定tag,则默认为latest
  • . :最后的点代表当前目录(Dockerfile所在目录), 也可以指定其他目录的Dockerfile

|-------------|--------------------------------------------------------------------------------------| | 1 2 | # 例如指定/root/dockerfile_demo目录 docker build -t click:1.0 /root/dockerfile_dem |

查看镜像列表

|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 | # 查看镜像列表: docker images # 结果 REPOSITORY TAG IMAGE ID CREATED SIZE click 1.0 d6ab0b9e64b9 10 minutes ago 89MB nginx latest 605c77e624dd 16 months ago 141MB mysql latest 3218b38490ce 17 months ago 517MB |

网络 {#网络}

在上面的案例, 我们已经创建了Java项目的容器, 其中往往Java项目需要访问其他容器中间件(MySQL,Redis等), 他们需要访问则需要通过网络

默认情况下, 所有容器都是以bridge(网桥)方式连接到Docker的一个虚拟网桥上

|---------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 1.用基本命令,寻找Networks.bridge.IPAddress属性 docker inspect mysql # 也可以使用format过滤结果 docker inspect --format= '{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' mysql # 得到IP地址如下: 172.17.0.2 # 2.然后通过命令进入dd容器 docker exec -it dd bash # 3.在容器内,通过ping命令测试网络 ping 172.17.0.2 # 结果 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.053 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.058 ms |

发现Ping通, 并没有什么问题

但是,容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能MySQL容器的IP会发生变化,连接会失败

官方文档 docker network | Docker Docs

常见网络命令有:

| 命令 | 说明 | 文档地址 | |---------------------------|--------------|-------------------------------------------------------------------------------------------------------| | docker network create | 创建一个网络 | docker network create | | docker network ls | 查看所有网络 | docs.docker.com | | docker network rm | 删除指定网络 | docs.docker.com | | docker network prune | 清除未使用的网络 | docs.docker.com | | docker network connect | 使指定容器连接加入某网络 | docs.docker.com | | docker network disconnect | 使指定容器连接离开某网络 | docker network disconnect | | docker network inspect | 查看网络详细信息 | docker network inspect |

自定义网络 {#自定义网络}

|---------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 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 | # 1.首先通过命令创建一个网络 docker network create qlh # 2.然后查看网络 docker network ls # 结果: NETWORK ID NAME DRIVER SCOPE e070f0159014 bridge bridge local cfb0c477c4dc host host local 9393a7da1c50 none null local f5084a25485a qlh bridge local # 其中,除了qlh以外,其它都是默认的网络 # 3.让dd和mysql都加入该网络,注意,在加入网络时可以通过--alias给容器起别名 # 这样该网络内的其它容器可以用别名互相访问! # 3.1.mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名 docker network connect qlh mysql -- alias db # 3.2.db容器,也就是我们的java项目 docker network connect qlh dd # 4.进入dd容器,尝试利用别名访问db # 4.1.进入容器 docker exec -it dd bash # 4.2.用db别名访问 ping db # 结果 PING db (172.18.0.2) 56(84) bytes of data. 64 bytes from mysql.qlh (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms 64 bytes from mysql.qlh (172.18.0.2): icmp_seq=2 ttl=64 time=0.056 ms # 4.3.用容器名访问 ping mysql # 结果: PING mysql (172.18.0.2) 56(84) bytes of data. 64 bytes from mysql.qlh (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms 64 bytes from mysql.qlh (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms |

现在可以通过别名(例如: db)访问

总结:

  • 在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
  • 在同一个自定义网络中的容器,可以通过别名互相访问

(旧)项目部署示例 {#旧-项目部署示例}

尝试部署黑马商城

项目结构:

  • hmall: 商城的后端代码
  • hmall-portal:商城用户端的前端代码
  • hmall-admin:商城管理端的前端代码

部署的容器及端口说明:

| 项目 | 容器名 | 端口 | 备注 | |--------------|---------|--------|-------------| | hmall | hmall | 8080 | 黑马商城后端API入口 | | hmall-portal | nginx | 18080 | 黑马商城用户端入口 | | hmall-admin | nginx | 18081 | 黑马商城管理端入口 | | mysql | mysql | 3306 | 数据库 |

在正式部署前,我们先删除之前的nginx、dd两个容器:

|-----------|-------------------------------| | 1 | docker rm -f nginx dd |

mysql容器中已经准备好了商城的数据,所以就不再删除了。

部署SpringBoot项目 {#部署SpringBoot项目}

hamll项目是一个maven聚合项目, 打开项目结构如下


hamll

----->hm-common 通用工具模块

----->hm-service 业务模块


其中我们需要部署的是hm-service模块, 其中配置文件采用了多环境的方式

  • application.yml
  • application-dev.yml
  • application-local.yml

其中的 application-dev.yaml 是部署到开发环境的配置, application-local.yaml 是本地运行时的配置

查看application.yaml,会发现其中的JDBC地址并未写死,而是读取变量:

|---------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 | # 启动端口 server: port: 9000 spring: # 环境修改 profile: active: dev # 数据库相关 1. db.host 2. db.pw datasource: url: jdbc:mysql://${db.host}:3306/hmall?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true username: root password: ${db.pw} driver-class-name: com.mysql.cj.jdbc.Driver |

这两个变量在 application-dev.ymlapplication-local.yml 中并不相同:

|---------------------------|--------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 | # application-dev.yml db: host: mysql pw: 123 # application-local.yml db: host: localhost pw: 123456 |

在dev开发环境(也就是Docker部署时)采用了mysql作为地址,刚好是我们的mysql容器名,只要两者在一个网络,就一定能互相访问

hm-service 目录下的 Dockerfilehm-service/target 目录下的 hm-service.jar 一起上传到虚拟机的 root 目录

部署项目

|------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # 1.构建项目镜像,不指定tag,则默认为latest docker build -t hmall . # 2.查看镜像 docker images # 结果 REPOSITORY TAG IMAGE ID CREATED SIZE hmall latest 0bb07b2c34b9 43 seconds ago 362MB docker-demo 1.0 49743484da68 24 hours ago 327MB nginx latest 605c77e624dd 16 months ago 141MB mysql latest 3218b38490ce 17 months ago 516MB # 3.创建并运行容器,并通过--network将其加入hmall网络,这样才能通过容器名访问mysql docker run -d --name hmall --network hmall -p 8080:8080 hmall |

测试,通过浏览器访问:http://你的虚拟机地址:8080/search/list。

部署前端 {#部署前端}

hmall-portalhmall-admin 是前端代码,需要基于nginx部署。在黑马资料中已经提供了nginx的部署目录

其中:

  • html 是静态资源目录,我们需要把 hmall-portal 以及 hmall-admin 都复制进去
  • nginx.conf 是nginx的配置文件,主要是完成对 html 下的两个静态资源目录做代理

我们现在要做的就是把整个nginx目录上传到虚拟机的 /root 目录下:

然后创建nginx容器并完成两个挂载:

  • /root/nginx/nginx.conf 挂载到 /etc/nginx/nginx.conf
  • /root/nginx/html 挂载到 /usr/share/nginx/html

由于需要让nginx同时代理hmall-portal和hmall-admin两套前端资源,因此我们需要暴露两个端口:

  • 18080:对应hmall-portal
  • 18081:对应hmall-admin

命令如下:

|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 | docker run -d \ --name nginx \ -p 18080:18080 \ -p 18081:18081 \ -v /root/nginx/html:/etc/nginx/html \ -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf \ --network hmall \ nginx |

测试,通过浏览器访问:http://你的虚拟机ip:18080

(新)项目部署 {#新-项目部署}

在Windows和Linux下部署其实是一样的,首先我们需要将 Dockerfileproject.jar 放在一个目录下面

例如 Dockerfile 示例如下

|------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 | # 添加 Java 8 镜像来源 FROM registry.cn-beijing.aliyuncs.com/hub-mirrors/openjdk:8-jdk-alpine #WORKDIR指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行。 WORKDIR /opt/docker/images/calyeedatabases/ # 添加 Spring Boot 包 ADD chat-server-1.0-SNAPSHOT.jar /chat-server-1.0-SNAPSHOT.jar EXPOSE 8080 EXPOSE 8090 # 执行启动命令 /chat-server-1.0-SNAPSHOT.jar需要和上面的一样 ENTRYPOINT ["java","-jar","/chat-server-1.0-SNAPSHOT.jar"] |

然后jar包也在当前目录,例如 chat-server-1.0-SNAPSHOT.jar

然后我们需要输入指令

|-----------|------------------------------------------------------------------| | 1 | docker build -f Dockerfile -t calyee/calyeechat:1.0 . |

然后就可以看到有镜像(calyee/calyeechat:1.0)了

我们需要将镜像跑起来

|-----------|-----------------------------------------------------------------------------------------| | 1 | docker run -d -p 8080:8080 -p 8090:8090 --name calyeechat calyee/calyeechat:1.0 |

在当前项目我们开了两个端口 所以需要映射两个端口出去(当前我们没有用到网桥,如需使用网桥可以参考整合下面小结#FastDFS)

然后 docker start calyeechat 即可,如果我们没有运行成功,需要查看报错信息,可以使用 docker logs 容器id .

DockerCompose {#DockerCompose}

在当前的项目部署示例中, 我们部署了 1)MySQL容器 2)Nginx容器 3) Java项目, 但是在以后复杂的项目中, 当然还要部署其他的中间件, 从而远远不止类似于当前的三个容器, 如果还像之前那样部署, 非常麻烦

而Docker Compose就可以帮助我们实现 多个相互关联的Docker容器的快速部署 。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器

基本语法 {#基本语法}

Docker Compose的YML语法详情见 Compose file version 3 reference | Docker Docs

在docker-compose文件中可以定义多个相互关联的应用容器,每一个应用容器被称为一个服务

在之前的MySQL部署时, 我们使用的命令示例是这样的

|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 | docker run -d \ --name mysql \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123456 \ -v ./mysql/data:/var/lib/mysql \ -v ./mysql/conf:/etc/mysql/conf.d \ -v ./mysql/init:/docker-entrypoint-initdb.d \ --network hmall mysql |

而使用Compose, 是这样的

|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | version: "3.8" services: mysql: image: mysql container_name: mysql ports: - "3306:3306" environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: 123 volumes: - "./mysql/conf:/etc/mysql/conf.d" - "./mysql/data:/var/lib/mysql" networks: - new networks: new: name: hmall |

对比如下:

| docker run 参数 | docker compose 指令 | 说明 | |-------------------|-----------------------|--------| | --name | container_name | 容器名称 | | -p | ports | 端口映射 | | -e | environment | 环境变量 | | -v | volumes | 数据卷配置 | | --network | networks | 网络 |

那么对于刚刚项目部署的样例则可以修改为

|------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 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 38 39 40 41 42 43 44 | version: "3.8" services: mysql: image: mysql container_name: mysql ports: - "3306:3306" environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: 123456 volumes: - "./mysql/conf:/etc/mysql/conf.d" - "./mysql/data:/var/lib/mysql" - "./mysql/init:/docker-entrypoint-initdb.d" networks: - hm-net hmall: build: context: . dockerfile: Dockerfile container_name: hmall ports: - "8080:8080" networks: - hm-net depends_on: - mysql nginx: image: nginx container_name: nginx ports: - "18080:18080" - "18081:18081" volumes: - "./nginx/nginx.conf:/etc/nginx/nginx.conf" - "./nginx/html:/usr/share/nginx/html" depends_on: - hmall networks: - hm-net networks: hm-net: name: hmall |

基本命令 {#基本命令}

编写好了Yaml文件, 就可以部署项目了

对于一些常见的命令 Overview of docker compose CLI | Docker Docs

语法如下

|-----------|--------------------------------------------| | 1 | docker compose [OPTIONS] [COMMAND] |

其中,OPTIONS和COMMAND都是可选参数,比较常见的有:

| 类型 | 参数或指令 | 说明 | |----------|-----------|--------------------------------------------------------| | Options | -f | 指定compose文件的路径和名称 | | Options | -p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 | | Commands | up | 创建并启动所有service容器 | | Commands | down | 停止并移除所有容器、网络 | | Commands | ps | 列出所有启动的容器 | | Commands | logs | 查看指定容器的日志 | | Commands | stop | 停止容器 | | Commands | start | 启动容器 | | Commands | restart | 重启容器 | | Commands | top | 查看运行的进程 | | Commands | exec | 在指定的运行中容器中执行命令 |

样例: Docker整合FastDFS {#样例-Docker整合FastDFS}

镜像

|-----------------|-----------------------------------------------------------------------------------| | 1 2 3 4 | # 1. 查找FastDFS docker search fastdfs # 2. 拉取镜像 docker pull delron/fastdfs |

tracker安装

|-----------|------------------------------------------------------------------------------------------------------------------------------------| | 1 | docker run -d --name tracker --network=yournetwork -v E:\dockercontainers\fastdfs\tracker:/var/fdfs delron/fastdfs tracker |

  • E:\dockercontainers\fastdfs\tracker 为挂载到本地的路径
  • --network=yournetwork 加入的网桥

storage安装

|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 | docker run -d -p 8888:8888 --name storage --network=yournetwork -e TRACKER_SERVER=172.18.0.2:22122 -v E:\dockercontainers\fastdfs\storage:/var/fdfs -e GROUP_NAME=group1 delron/fastdfs storage |

  • TRACKER_SERVER 为上面的 tracker 连接到的网桥的地址
  • GROUP_NAME 分组名

测试: 在storage容器中测试使用命令上传图片

|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 | # 进入容器内bash指令模式 docker exec -it storage bash # 进入/var/fdfs目录 cd /var/fdfs # 加载位于E:\dockercontainers\fastdfs\storage下的文件 3.png # E:\dockercontainers\fastdfs\storage为映射地址 # 加载完成会返回一串字符路径 group1/M00/00/00/rBIAA2VLaFSAXi66AABGbuqCV2g017.jpg /usr/bin/fdfs_upload_file /etc/fdfs/client.conf 3.png # 最后通过映射端口访问 http://localhost:8888/group1/M00/00/00/rBIAA2VLaFSAXi66AABGbuqCV2g017.jpg |

应用: SpringBoot整合FastDFS {#应用-SpringBoot整合FastDFS}

导入第三方依赖

|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | <!--fastDFS--> < dependency > < groupId > com.luhuiguo </ groupId > < artifactId > fastdfs-spring-boot-starter </ artifactId > < version > 0.2.0 </ version > </ dependency > |

配置SpringBoot Yaml

|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | fdfs: # docker网桥分配的IP地址 tracker的地址 tracker-list: 172.18 .0 .4 :22122 so-timeout: 6000 # 设置读取时间 connect-timeout: 1000 # 设置连接时间 |

编写一个简单的UploadService

|---------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 注入Fast客户端 @Autowired private FastFileStorageClient fastFileStorageClient; public String uploadFile (MultipartFile multipartFile) { StorePath storePath = null ; try { storePath = fastFileStorageClient.uploadFile( "" , multipartFile.getInputStream() , multipartFile.getSize() , "jpg" ); log.info( "Group:{},Path:{},FullPath:{}" , storePath.getGroup(), storePath.getPath(), storePath.getFullPath()); } catch (IOException e) { log.error( "uploadFile发生了异常,{}" , e.getMessage()); return null ; } return storePath.getFullPath(); } |

该starter源码参考: [luhuiguo]( luhuiguo/fastdfs-spring-boot-starter: Spring Boot FastDFS Starter (github.com) ), 关于此依赖版本, 参考 maven仓库 , 搜索fastdfs (当前github中的readme文件介绍指定的是0.1.0)

应用通信 {#应用通信}

环境: SpringBoot项目,Docker容器有: Redis, MySQL, FastDFS

当前项目的拓扑图示例如下:

  • 对于Windows访问容器: Windows访问 暴露的端口 , 例如访问docker容器中的nginx暴露的8888端口, 从而访问FastDFS存储的照片

  • 对于Docker容器内部通信: 容器之间可以通过网桥通信, 例如我的Application应用(SpringBoot), 需要访问MySQL和Redis等容器, 则可以访问 网桥 分配的ip地址(如图), 实现通信。查看如何查询网桥情况: docker network inspect your_bridge

关于线上环境: 在Docker内部则是通过网桥访问容器原生端口(例如MySQL:3306), SpringBoot的配置文件配置样例

|---------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | fdfs: # docker网桥分配的IP地址 tracker的地址 tracker-list: 172.18 .0 .4 :22122 so-timeout: 6000 # 设置读取时间 connect-timeout: 1000 # 设置连接时间 server: port: 9999 # 服务端口 spring: datasource: # docker网桥分配的IP地址 url: jdbc:mysql://172.18.0.2:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver #Redis相关配置 redis: host: 172.18 .0 .5 # docker网桥分配的IP地址 port: 6379 #password:123456 database: 0 #0是0号数据库,redis默认开启的16个数据库 timeout: 5000 #超时时间 |

例如Redis在网桥上的IP为172.18.0.5, 则需要在配置文件中配置网桥地址。 (结构图参考该小结首照片)

赞(0)
未经允许不得转载:工具盒子 » Docker