Docker

1.基本操作

登录docker hub

1
docker login   

使用 docker tag 命令给本地镜像打标签

1
docker tag demo-docker:1.0 lypsdocker/teacherspringboot1:1.0

这里,demo-docker:1.0 是你本地镜像的名字和标签,lypsdocker/teacherspringboot1:1.0 是你想要推送到 Docker Hub 的用户名、仓库名和标签。

使用 docker push 命令推送镜像到 Docker Hub

1
docker push lypsdocker/teacherspringboot1:1.0

查看正在运行的容器

1
docker ps

查看所有容器(包括已停止的)

1
docker ps -a

停止容器

1
docker stop demo-docker

这将停止名为demo-docker的容器.

启动容器(如果之前已经停止)

1
docker start demo-docker

删除容器

1
docker rm demo-docker

进入容器内部

1
docker exec -it demo-docker /bin/bash

2.创建镜像和容器并上传到Docker hub

3.从Docker bub 上拉取镜像并创建容器并运行

拉取镜像

1
docker pull lypsdocker/teacherspringboot1:1.0

你的Docker Hub用户名是lypsdocker,并且你要拉取的镜像名称是demo-docker,标签是1.0

运行docker容器

1
docker run -d --name my-springboot-app -p 9090:9090 lypsdocker/teacherspringboot1:1.0
1
docker run -d --name my-container-name my-app
  • -d:在“分离”模式下运行容器,这意味着容器将在后台运行,并返回容器ID。

  • --name my-container-name:给容器指定一个名称,这样你可以更容易地引用它。

  • -p--publish:将容器的端口映射到宿主机的端口。例如,-p 8080:80 会将容器内的80端口映射到宿主机的8080端口。

  • -v--volume:挂载宿主机的目录或文件到容器内。例如,-v /host/path:/container/path 会将宿主机的/host/path目录挂载到容器的/container/path目录。

  • --env-e:设置环境变量。例如,-e "VAR_NAME=value" 会在容器内设置一个名为VAR_NAME的环境变量,其值为value

  • --network:指定容器使用的网络。

  • --restart:设置容器的重启策略。例如,--restart=always 会使容器在退出时总是重新启动。

数据卷

是一个虚拟目录,是容器内目录和宿主机目录之间双向映射的桥梁

2

数据卷操作命令

3

本地目录挂载

  • 在执行docvker run命令时,使用 -v 本地目录:容器内目录 可以完成本地目录挂载

  • 本地目录必须以“/” 或”./“开头,如果直接以名称开头,会被识别为数据卷而非本地目录

Dockerfile语法

一个文本文件,其中包含一个个指令,用指令来执行上面操作来构建镜像。

4

构建镜像

1
2
3
4
# 进入镜像目录
cd /root/demo
# 开始构建
docker build -t docker-demo:1.0 .
  • docker build : 就是构建一个docker镜像
  • -t docker-demo:1.0-t参数是指定镜像的名称(repositorytag
  • . : 最后的点是指构建时Dockerfile所在路径,由于我们进入了demo目录,所以指定的是.代表当前目录,也可以直接指定Dockerfile目录:
    • # 直接指定Dockerfile目录
      docker build -t docker-demo:1.0 /root/demo
      
      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



      我们的容器之间能否互相访问呢?测试一下

      首先,我们查看下MySQL容器的详细信息,重点关注其中的网络IP地址:

      ```Bash
      # 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

发现可以互联,没有问题。

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

所以,我们必须借助于docker的网络功能来解决这个问题,官方文档:

https://docs.docker.com/engine/reference/commandline/network/

常见命令有:

命令 说明 文档地址
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 hmall

# 2.然后查看网络
docker network ls
# 结果:
NETWORK ID NAME DRIVER SCOPE
639bc44d0a87 bridge bridge local
403f16ec62a2 hmall bridge local
0dc0f72a0fbb host host local
cd8d3e8df47b none null local
# 其中,除了hmall以外,其它都是默认的网络

# 3.让dd和mysql都加入该网络,注意,在加入网络时可以通过--alias给容器起别名
# 这样该网络内的其它容器可以用别名互相访问!
# 3.1.mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名
docker network connect hmall mysql --alias db
# 3.2.db容器,也就是我们的java项目
docker network connect hmall 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.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from mysql.hmall (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.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms

现在无需记住IP地址也可以实现容器互联了。

总结

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

部署java项目

部署后端

现在我们以部署黑马的hmall项目为例

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

5

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

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

  1. 将项目打为jar包

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

  3. 部署项目

    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
  4. 测试,通过浏览器访问:http://你的虚拟机地址:8080/search/list

部署前端

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

6

其中:

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

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

img

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

  • /root/nginx/nginx.conf挂载到/etc/nginx/ng``inx.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:/usr/share/nginx/html \
-v /root/nginx/nginx.conf:/etc/nginx/nginx.conf \
--network hmall \
nginx

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

DockerCompose

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

基本语法

docker-compose.yml文件的基本语法可以参考官方文档

docker-compose文件中可以定义多个相互关联的应用容器,每一个应用容器被称为一个服务(service)。由于service就是在定义某个应用的运行时参数,因此与docker run参数非常相似。

举例来说,用docker run部署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=123 \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
--network hmall
mysql

如果用docker-compose.yml文件来定义,就是这样:

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

那么黑马商城部署文件:

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: 123
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

基础命令

编写好docker-compose.yml文件,就可以部署项目了

1
docker compose [OPTIONS] [COMMAND]

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

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