首页 > 其他分享 >Docker 使用教程

Docker 使用教程

时间:2023-05-09 13:23:49浏览次数:37  
标签:容器 教程 -- fantastic lasers 使用 docker root Docker

Docker 使用教程

Docker 的简介和安装

Docker 是一个应用打包、分发、部署的工具。你也可以把它理解为一个轻量的虚拟机,它只虚拟你软件需要的运行环境,多余的一点都不要,而普通虚拟机则是一个完整而庞大的系统,包含各种不管你要不要的软件。

Docker 为什么比虚拟机快?

  1. Docker 有着比虚拟机更少的抽象层
  2. Docker 利用的是宿主机的内核,而 vm 需要 Guest OS,所以新建一个容器的时候,docker 不需要像虚拟机一样重新加载一个操作系统内核,避免引导。
特性 普通虚拟机 Docker
跨平台 通常只能在桌面级系统运行,例如 Windows/Mac 支持的系统非常多,各类 windows 和 Linux 都支持
性能 性能损耗大,内存占用高,因为是把整个完整系统都虚拟出来了 性能好,只虚拟软件所需运行环境,最大化减少没用的配置
自动化 需要手动安装所有东西 一个命令就可以自动部署好所需环境
稳定性 稳定性不高,不同系统差异大 稳定性好,不同系统都一样部署方式
  • 打包:就是把软件所需的依赖、第三方库、软件打包到一起,变成一个安装包
  • 分发:你可以把打包好的安装包上传到一个镜像仓库,其他人可以非常方便的获取和安装
  • 部署:拿着安装包就可以一个命令运行起来你的应用,自动模拟出一摸一样的运行环境,不管是在 Windows/Mac/Linux

Docker 部署的优势?

  • 常规应用开发部署方式:自己在 windows 上开发、测试 \(\to\) 到 Linux 服务器配置运行环境部署

  • Docker 开发部署流程:自己在 windows 上开发 \(\to\) 打包为 Docker 镜像(可以理解为软件安装包)\(\to\) 各种服务器上只需要一个命令部署好,确保了不同机器上跑都是一致的运行环境,例如易文档、SVNBucket 的私有化部署就是用 Docker,轻松应对客户的各种服务器。

Docker 通常用来做什么?

  • 应用分发、部署,方便传播给他人安装,特别是开源软件和提供私有部署的应用
  • 快速安装测试 / 学习软件,用完就丢(类似小程序),不把时间浪费在安装软件上
  • 多个版本共存,不污染系统
  • Windows 上体验各种 Linux 系统

理解两个重要概念:

  • 镜像 (image):可以理解为软件安装包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、库、环境变量和配置文件。一个模板,可以通过这个模板来创建容器服务,通过这个镜像可以创建多个容器
  • 容器 (container)):软件安装后的状态,每个软件运行环境都是独立的、隔离的,称之为容器,最终服务运行或者项目运行就是在容器中
  • 仓库 (repository):存放镜像的地方,分为公有仓库和私有仓库

image-20230419155407219

安装链接

  1. 桌面版:https://www.docker.com/products/docker-desktop

    1. 直接按步骤操作
  2. 服务器版:https://docs.docker.com/engine/install/#server

    1. 使用 Xshell 连接远程服务器
    2. 查看 Linux 发行版名称和版本号:uname -r
    # 系统版本
    [root@fantastic-lasers-1 ~]# uname -r
    4.10.4-1.el7.elrepo.x86_64
    [root@fantastic-lasers-1 ~]# cat /etc/os-release
    NAME="CentOS Linux"
    VERSION="7 (Core)"
    ID="centos"
    ID_LIKE="rhel fedora"
    VERSION_ID="7"
    PRETTY_NAME="CentOS Linux 7 (Core)"
    ANSI_COLOR="0;31"
    CPE_NAME="cpe:/o:centos:centos:7"
    HOME_URL="https://www.centos.org/"
    BUG_REPORT_URL="https://bugs.centos.org/"
    
    CENTOS_MANTISBT_PROJECT="CentOS-7"
    CENTOS_MANTISBT_PROJECT_VERSION="7"
    REDHAT_SUPPORT_PRODUCT="centos"
    REDHAT_SUPPORT_PRODUCT_VERSION="7"
    
    1. 查询安装文档,卸载旧版本,然后通过 repository 安装
    # 1. 卸载旧版本
    sudo yum remove docker \
                    docker-client \
                    docker-client-latest \
                    docker-common \
                    docker-latest \
                    docker-latest-logrotate \
                    docker-logrotate \
                    docker-engine
    
    # 2. 需要的安装包
    sudo yum install -y yum-utils
    # 默认是国外的地址
    sudo yum-config-manager \
        --add-repo \
        https://download.docker.com/linux/centos/docker-ce.repo
    # 换成阿里云的地址
    sudo yum-config-manager \
        --add-repo \
        https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
    # 更新 yum 软件包索引
    yum makecache fast
    
    # 安装 docker
    sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
    # start docker
    sudo systemctl start docker
    
    # 验证是否启动成功
    sudo docker version
    
    [root@fantastic-lasers-1 ~]# docker version
    Client: Docker Engine - Community
     Version:           23.0.4
     API version:       1.42
     Go version:        go1.19.8
     Git commit:        f480fb1
     Built:             Fri Apr 14 10:36:38 2023
     OS/Arch:           linux/amd64
     Context:           default
    
    Server: Docker Engine - Community
     Engine:
      Version:          23.0.4
      API version:      1.42 (minimum version 1.12)
      Go version:       go1.19.8
      Git commit:       cbce331
      Built:            Fri Apr 14 10:34:14 2023
      OS/Arch:          linux/amd64
      Experimental:     false
     containerd:
      Version:          1.6.20
      GitCommit:        2806fc1057397dbaeefbea0e4e17bddfbd388f38
     runc:
      Version:          1.1.5
      GitCommit:        v1.1.5-0-gf19387a
     docker-init:
      Version:          0.19.0
      GitCommit:        de40ad0
    
    1. 运行 hello-world
    sudo docker run hello-world
    
    输出:
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    2db29710123e: Pull complete
    Digest: sha256:4e83453afed1b4fa1a3500525091dbfca6ce1e66903fd4c01ff015dbcb1ba33e
    Status: Downloaded newer image for hello-world:latest
    
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    
    To generate this message, Docker took the following steps:
     1. The Docker client contacted the Docker daemon.
     2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
        (amd64)
     3. The Docker daemon created a new container from that image which runs the
        executable that produces the output you are currently reading.
     4. The Docker daemon streamed that output to the Docker client, which sent it
        to your terminal.
    
    To try something more ambitious, you can run an Ubuntu container with:
     $ docker run -it ubuntu bash
    
    1. 查看一下下载的 hello-world 镜像
    sudo docker images
    
    输出:
    REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
    hello-world   latest    feb5d9fea6a5   19 months ago   13.3kB
    
    1. 卸载 Docker Engine:如果需要卸载再卸载
    # Uninstall the Docker Engine, CLI, Containerd, and Docker Compose packages: 卸载依赖
    sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
    
    # Images, containers, volumes, or customized configuration files on your host are not automatically removed. To delete all images, containers, and volumes: 删除目录
    sudo rm -rf /var/lib/docker
    sudo rm -rf /var/lib/containerd
    
  3. 阿里云镜像加速

    1. 登录阿里云网站 \(\to\) 产品 \(\to\) 容器镜像服务
    2. 获取镜像加速地址:https://6jotehk6.mirror.aliyuncs.com
    3. 配置镜像加速器
    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://6jotehk6.mirror.aliyuncs.com"]
    }
    EOF
    sudo systemctl daemon-reload
    
    sudo systemctl restart docker
    

Docker 的底层原理:

  1. Docker 是一个 Client-Server 结构的系统,Docker 的守护进程运行在主机上,通过 Socket 从客户端访问。
  2. DockerServer 接收到 Docker-Client 的指令,就会执行这个命令

Docker 的常用命令

帮助命令

帮助文档

docker version  # 显示 docker 的版本信息
docker info     # 显示 docker 的系统信息,包括镜像和容器的数量
docker 命令 --help

镜像命令

  • docker images:查看本地主机上的所有镜像
[root@fantastic-lasers-1 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   19 months ago   13.3kB


Options:
  -a, --all             显示全部镜像
  -q, --quiet           只显示镜像的 ID
  • docker search:搜索镜像
[root@fantastic-lasers-1 ~]# docker search mysql
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   14049     [OK]
mariadb                         MariaDB Server is a high performing open sou…   5367      [OK]
percona                         Percona Server is a fork of the MySQL relati…   605       [OK]
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   784       [OK]

# 可选项,通过搜索来过滤
	--filter=STARS=3000  # 搜索出来的镜像就是 STARS 大于 3000 的
  • docker pull [:tag]:下载镜像
[root@fantastic-lasers-1 ~]# docker pull mysql
Using default tag: latest  # 如果不写 tag,默认就是 latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete   # 分层下载,docker image 的核心,联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709   # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest  # 真实地址

# 等价于
docker pull docker.io/library/mysql:latest

###  指定版本下载  ###
docker pull mysql:5.7
# https://hub.docker.com/_/mysql 找到相关版本

[root@fantastic-lasers-1 ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
  • docker rmi -f 容器id 容器id 容器id:删除镜像,一般通过 id 来删除
  • docker rmi -f $(docker images -aq):批量删除
[root@fantastic-lasers-1 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
mysql         5.7       c20987f18b13   16 months ago   448MB
mysql         latest    3218b38490ce   16 months ago   516MB
hello-world   latest    feb5d9fea6a5   19 months ago   13.3kB
[root@fantastic-lasers-1 ~]# docker rmi -f c20987f18b13
Untagged: mysql:5.7
Untagged: mysql@sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Deleted: sha256:c20987f18b130f9d144c9828df630417e2a9523148930dc3963e9d0dab302a76
Deleted: sha256:6567396b065ee734fb2dbb80c8923324a778426dfd01969f091f1ab2d52c7989
Deleted: sha256:0910f12649d514b471f1583a16f672ab67e3d29d9833a15dc2df50dd5536e40f
Deleted: sha256:6682af2fb40555c448b84711c7302d0f86fc716bbe9c7dc7dbd739ef9d757150
Deleted: sha256:5c062c3ac20f576d24454e74781511a5f96739f289edaadf2de934d06e910b92
  • docker history 镜像id:查看镜像的构建过程

容器命令

说明:我们有了镜像才可以创建容器。

  1. 下载一个 centos 镜像来测试学习:docker pull centos

  2. 新建容器并启动

docker run [可选参数] image

# 参数说明
--name="Name"   容器名字
-d              后台方式运行
-it             使用交互方式运行,进入容器查看内容
-p              指定容器的端口 -p 8080:8080 主机端口:容器端口
-P              随机指定端口

# 测试:启动并进入容器
[root@fantastic-lasers-1 ~]# docker run -it centos /bin/bash
# 查看容器内的 centos
[root@7f71ee15591d /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
# 从容器中退出,回到主机
[root@7f71ee15591d /]# exit
exit
[root@fantastic-lasers-1 ~]#

  1. docker ps:列出所有运行中容器
[root@fantastic-lasers-1 ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                          PORTS     NAMES
7f71ee15591d   centos         "/bin/bash"   3 minutes ago   Exited (0) About a minute ago             wonderful_bhabha
0948f34b9e54   feb5d9fea6a5   "/hello"      3 hours ago     Exited (0) 3 hours ago                    sweet_lamarr
5efeea0262e2   feb5d9fea6a5   "/hello"      3 hours ago     Exited (0) 3 hours ago                    pensive_benz

# 参数说明
-a              列出当前正在运行的容器 + 带出历史运行过的容器
-n=?            显示最近创建的容器
-q              只显示容器的编号
  1. exit:退出容器
exit  # 直接容器停止并退出
ctrl + P + Q  # 容器不停止退出
  1. docker rm:删除容器
docker rm 容器id  # 删除指定的容器,不能删除正在运行的容器,如果要强制删除 + -f
docker rm -f $(docker ps -aq)  # 删除所有容器
docker ps -a -q|xargs docker rm  # 删除所有容器
  1. 启动和停止容器的操作
docker start 容器id      # 启动容器
docker restart 容器id    # 重启容器
docker stop 容器id       # 停止当前正在运行的容器
docker kill 容器id       # 强制停止当前容器

常用的其他命令

  • docker run -d 镜像名:后台启动容器
[root@fantastic-lasers-1 ~]# docker run -d centos
1457cf8b498c295b94c06906eb4a3bfdc95951065bc5078350508cca7d35d741

# 问题:docker ps 发现 centos 停止了
# 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker 发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
  • docker logs:查看日志
# --tail num: 要显示的日志的条数
docker logs -tf --tail 10 1cf8c5669c1b

# -t: 显示日志条目的时间戳
# -f: 实时跟踪日志输出
# --tail num: 要显示的日志条数
# 自己写一段 shell 脚本
"while true;do echo lockegogo;sleep 1;done"

[root@fantastic-lasers-1 ~]# docker run -d centos /bin/sh -c "while true;do echo lockegogo;sleep 1;done"

[root@fantastic-lasers-1 ~]# docker ps
CONTAINER ID   IMAGE
2e6172cd4191   centos

# 显示日志
[root@fantastic-lasers-1 ~]# docker logs -tf --tail 10 2e6172cd4191

2023-04-22T03:02:23.909868744Z lockegogo
2023-04-22T03:02:24.912591695Z lockegogo
2023-04-22T03:02:25.915164808Z lockegogo
2023-04-22T03:02:26.917449632Z lockegogo
2023-04-22T03:02:27.919790967Z lockegogo
  • top:查看容器里的进程信息
[root@fantastic-lasers-1 ~]# docker top 2e6172cd4191
UID                 PID                 PPID                C                   STIME               TTY
root                17626               17602               0                   11:00               ?
root                18393               17626               0                   11:05               ?
  • inspect:查看镜像的元数据
[root@fantastic-lasers-1 ~]# docker inspect 2e6172cd4191
  • exec:进入当前正在运行的容器
# 容器通常都是使用后台方式运行的,我们有时需要进入容器,修改一些配置

# 命令 1
docker exec -it 容器id bashShell

# 测试
[root@fantastic-lasers-1 ~]# docker exec -it 2e6172cd4191 /bin/bash
[root@2e6172cd4191 /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@2e6172cd4191 /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 03:00 ?        00:00:00 /bin/sh -c while true;do echo lockegogo;sleep 1;done
root       740     0  0 03:12 pts/0    00:00:00 /bin/bash
root       768     1  0 03:12 ?        00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/
root       769   740  0 03:12 pts/0    00:00:00 ps -ef

# 命令 2
docker attach 容器id

[root@fantastic-lasers-1 ~]# docker attach 2e6172cd4191
正在执行当前的代码...

# 区别
# docker exec: 进入容器后开启一个新的终端,可以在里面操作
# docker attach: 进入容器正在执行的终端,不会启动新的进程
  • cp:从容器内拷贝文件到主机
# m
docker cp 容器id:容器内路径 目的地主机路径

# 进入容器内部
[root@fantastic-lasers-1 ~]# docker attach 2e6172cd4191
[root@fantastic-lasers-1 ~]# cd /home
# 在容器内新建一个文件
[root@fantastic-lasers-1 ~]# touch test.java
[root@fantastic-lasers-1 ~]# exit
# 容器是否在运行无关进行,只要容器存在,容器内的文件就会一直存在
[root@fantastic-lasers-1 ~]# docker ps -a
# 将文件拷贝出来到主机上
[root@fantastic-lasers-1 ~]# docker cp 2e6172cd4191:/home/test.java /home

# 拷贝是一个手动过程,未来我们1使用 -v 卷的技术,可以实现自动同步

cmd_logic

Docker 快速安装软件

直接安装的缺点

  • 安装麻烦,可能有各种依赖,运行报错。例如:WordPressElasticSearchRedisELK
  • 可能对 Windows 并不友好,运行有各种兼容问题,软件只支持 Linux 上跑
  • 不方便安装多版本软件,不能共存。
  • 电脑安装了一堆软件,拖慢电脑速度。
  • 不同系统和硬件,安装方式不一样

Docker 安装的优点

  • 一个命令就可以安装好,快速方便
  • 有大量的镜像,可直接使用
  • 没有系统兼容问题,Linux 专享软件也照样跑
  • 支持软件多版本共存
  • 用完就丢,不拖慢电脑速度
  • 不同系统和硬件,只要安装好 Docker 其他都一样了,一个命令搞定所有

安装 Redis

Docker 官方镜像仓库查找 Redishttps://hub.docker.com/

一个命令跑起来:docker run -d -p 6379:6379 --name redis redis:latest

命令参考:https://docs.docker.com/engine/reference/commandline/run/

安装 Wordpress

新建 yaml 文件:

version: '3.1'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:

在文件存放处打开 cmd 运行:docker-compose up -d

安装 nginx

Nginx 是一款轻量级的 Web 服务器、反向代理服务器,反向代理服务器在客户端和 Web 服务器之间起到中介作用,它将客户端的请求转发到后端服务器,并将响应发送回客户端,同时隐藏了后端服务器的细节。

# 拉取镜像
[root@fantastic-lasers-1 ~]# dokcer pull nginx

# 启动镜像
[root@fantastic-lasers-1 ~]# docker run -d --name nginx01 -p 3344:80 nginx
061756b547f6415e4ca669065ca6a521c50beb04f75fff89259a79f70c5eb54e
[root@fantastic-lasers-1 ~]# docker ps

# 本机测试
# curl:不带任何参数时,curl 就是发出 GET 请求
[root@fantastic-lasers-1 ~]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# 进入容器
[root@fantastic-lasers-1 ~]# docker exec -it nginx01 /bin/bash
root@061756b547f6:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@061756b547f6:/# cd /etc/nginx
root@061756b547f6:/etc/nginx# ls
conf.d	fastcgi_params	mime.types  modules  nginx.conf  scgi_params  uwsgi_params

思考问题:我们每次改动 nginx 配置文件,都需要进入容器内部?十分麻烦,我们要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部就可以自动修改?

答案: -v 数据卷

安装 tomcat

docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台,停止了容器之后,容器还是可以查到,但是加上 --rm 之后,容器用完就删除,一般用来测试

[root@fantastic-lasers-1 ~]# docker pull tomcat

# 启动运行
[root@fantastic-lasers-1 ~]# docker run -d -p 3355:8080 --name tomcat01 tomcat

# 测试访问没有问题

# 进入容器
[root@fantastic-lasers-1 ~]# docker exec -it tomcat01 /bin/bash

发现问题:

  1. linux 命令少了
  2. 没有 webapps

这是阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除掉了,只保证最小可运行的环境。

思考问题:我们以后要部署项目,如果每次都要进入容器,是不是十分的麻烦?我们要是可以在容器外部提供一个映射路径,webapps,我们在外部放置项目,就自动同步到内部就好了!

安装 ES + Kibana

[root@fantastic-lasers-1 ~]# docker pull elasticsearch

[root@fantastic-lasers-1 ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch

# 查看容器占用内存情况
[root@fantastic-lasers-1 ~]# docker stats

CONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT    MEM %     NET I/O     BLOCK I/O        PIDS
e901ec719765   elasticsearch   0.21%     245.7MiB / 1008MiB   24.38%    906B / 0B   83.4MB / 156kB   36

[root@fantastic-lasers-1 ~]# curl localhost:9200
{
  "name" : "025Nxqc",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "tA3Bvd-qTGmfJZI27oZEPg",
  "version" : {
    "number" : "5.6.12",
    "build_hash" : "cfe3d9f",
    "build_date" : "2018-09-10T20:12:43.732Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"
}

思考:使用 Kibana 连接 es

更多相关命令

  • docker ps:查看当前运行中的容器
  • docker images:查看镜像列表
  • docker rm container-id:删除指定 id 的容器
  • docker stop/start container-id:停止 / 启动指定 id 的容器
  • docker rmi iamge-id:删除指定 id 的镜像
  • docker volume ls:查看 volume 的列表
  • docker network ls:查看网络列表

制作自己的镜像

使用教程

commit

docker commit # 提交容器成为一个新的副本

# 命令和 git 原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

实战测试:

[root@fantastic-lasers-1 ~]# docker run -it -p 8080:8080 tomcat

[root@fantastic-lasers-1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED              STATUS
05c01709e8ce   tomcat    "catalina.sh run"   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp

[root@fantastic-lasers-1 ~]# docker exec -it 05c01709e8ce /bin/bash
root@05c01709e8ce:/usr/local/tomcat# cp webapps.dist/* webapps
root@05c01709e8ce:/usr/local/tomcat# cd webapps
root@05c01709e8ce:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

把自己写好的镜像提交上去,以后我们就使用修改过的镜像即可:

[root@fantastic-lasers-1 ~]# docker commit -m="add webapps app" -a="LK" 05c01709e8ce tomcat02:1.0
sha256:d214b44cc1784f4660d7d1b8762e8ebe09122e84b43a59ff0846037003aff86e
[root@fantastic-lasers-1 ~]# docker images
REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
tomcat02        1.0       d214b44cc178   3 seconds ago   684MB
nginx           latest    605c77e624dd   15 months ago   141MB
tomcat          latest    fb5657adc892   16 months ago   680MB
centos          latest    5d0da3dc9764   19 months ago   231MB
elasticsearch   latest    5acf0e8da90b   4 years ago     486MB

如果你想要保存当前容器的状态,就可以通过 commit 来提交,获得一个镜像,就好像我们之前学习 VM 时的快照!

Dockerfile

Dockerfile 介绍

Dockerfile 就是构建 docker 镜像的构建文件!命令脚本!通过这个脚本可以生成一个镜像,镜像是一层一层的,脚本就是一个一个的命令,每个命令都是一层!

举个栗子:

[root@fantastic-lasers-1 docker-test-volume]# pwd
/home/docker-test-volume
# 1. 编写 dockerfile
[root@fantastic-lasers-1 docker-test-volume]# vim dockerfile1

FROM centos

VOLUME ["volume01","volume02"] # 匿名挂载

CMD echo "----end----"
CMD /bin/bash
# 2. docker build dockerfile 成为一个镜像
# -t: 为将要构建的镜像命名,注意镜像名前面是不能有斜杠的
# .: 参数表示 Docker 将在当前目录中查找 Dockerfile 文件,以构建新的镜像
[root@fantastic-lasers-1 docker-test-volume]# docker build -f dockerfile1 -t lk/centos .
[+] Building 0.1s (5/5) FINISHED
 => [internal] load build definition from dockerfile1                                             0.0s
 => => transferring dockerfile: 120B                                                              0.0s
 => [internal] load .dockerignore                                                                 0.0s
 => => transferring context: 2B                                                                   0.0s
 => [internal] load metadata for docker.io/library/centos:latest                                  0.0s
 => [1/1] FROM docker.io/library/centos                                                           0.0s
 => exporting to image                                                                            0.0s
 => => exporting layers                                                                           0.0s
 => => writing image sha256:0282d836c4f5ab8268cf4ebcf33ca7109bd03217f82358c4fa764466139852f2      0.0s
 => => naming to docker.io/library/lk/centos                                                      0.0s
[root@fantastic-lasers-1 docker-test-volume]# docker images
REPOSITORY      TAG       IMAGE ID       CREATED             SIZE
tomcat02        1.0       d214b44cc178   About an hour ago   684MB
nginx           latest    605c77e624dd   15 months ago       141MB
tomcat          latest    fb5657adc892   16 months ago       680MB
mysql           latest    3218b38490ce   16 months ago       516MB
lk/centos       latest    0282d836c4f5   19 months ago       231MB
centos          latest    5d0da3dc9764   19 months ago       231MB
elasticsearch   latest    5acf0e8da90b   4 years ago         486MB
# 3. 测试运行:docker run
[root@fantastic-lasers-1 docker-test-volume]# docker run -it 0282d836c4f5 /bin/bash
[root@b02e20395614 /]# ls -l
total 56
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Apr 22 08:48 dev
drwxr-xr-x   1 root root 4096 Apr 22 08:47 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4096 Sep 15  2021 lost+found
drwxr-xr-x   2 root root 4096 Nov  3  2020 media
drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt
drwxr-xr-x   2 root root 4096 Nov  3  2020 opt
dr-xr-xr-x 138 root root    0 Apr 22 08:47 proc
dr-xr-x---   2 root root 4096 Sep 15  2021 root
drwxr-xr-x  11 root root 4096 Sep 15  2021 run
lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov  3  2020 srv
dr-xr-xr-x  13 root root    0 Apr 22 08:47 sys
drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp
drwxr-xr-x  12 root root 4096 Sep 15  2021 usr
drwxr-xr-x  20 root root 4096 Sep 15  2021 var
drwxr-xr-x   2 root root 4096 Apr 22 08:47 volume01
drwxr-xr-x   2 root root 4096 Apr 22 08:47 volume02
# 上面两个目录就是我们生成镜像的时候自动挂载的,数据卷目录
# 4. 发布镜像:docker push

注意:很多官方镜像都是基础包,很多功能都没有,我们通常会自己搭建镜像。

Dockerfile 构建过程

Dockerfile 命令:

  1. 每个保留关键字(指令)都必须是大写字母
  2. 执行从上到下顺序执行
  3. # 表示注释
  4. 每一个指令都会创建提交一个新的镜像层,并提交!
  5. dockerfile 是面向开发的,我们以后要发布项目,做镜像,就需要编写 dockerfile 文件
k8s记录-Dockerfile详解- 信方- 博客园

img

实战测试

Docker Hub 中 99% 的镜像都是从基础镜像构建过来的 FROM scratch,然后配置需要的软件和配置来进行构建。

接下来我们创建一个自己的 centos:

# 1. 编写 dockerfile
[root@fantastic-lasers-1 home]# cd dockerfile/
[root@fantastic-lasers-1 dockerfile]# vim mydockerfile-centos
[root@fantastic-lasers-1 dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER lockegogo<[email protected]>

ENV MYPATH /usr/local
WORKDIR $MYPATH

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

EXPOSE 80

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash

# 2. 通过文件构建镜像
[root@fantastic-lasers-1 dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .

# 3. 测试运行
[root@fantastic-lasers-1 dockerfile]# docker run -it mycentos:0.1

SpringBoot 的 web 项目构建 Docker 镜像

  1. 打包应用:在终端进入项目跟目录,使用 maven 将应用程序打包成可运行的 jar 文件:mvn clean package,或者直接在 IDEA 界面点击右边的 Maven \(\to\) 项目 \(\to\) 生命周期 \(\to\) clean \(\to\) package,构建成功之后在 target 文件里可以看到 jar 包
# 在本地测试运行
java -jar springboot-03-web-0.0.1-SNAPSHOT.jar
  1. 编写 Dockerfile:在项目根目录下创建 Dockerfile 文件,该文件用于描述 Docker 镜像的构建过程:
# 基于 alpine 版本的 OpenJDK 19 镜像构建新的镜像
# 注意这里的版本要和项目创建时的版本一致
FROM openjdk:19-jdk-alpine
LABEL authors="Lockegogo"

# 将应用的 jar 包复制到容器中并更名为 app.jar
COPY target/springboot-03-web-0.0.1-SNAPSHOT.jar app.jar

# 暴露 8080 端口,使得其他容器或主机可以连接该端口
EXPOSE 8080

# 使用 java 命令启动应用
ENTRYPOINT ["java", "-jar", "app.jar"]
  1. 构建镜像:在终端进入项目根目录,并在该目录下执行以下命令构建 Docker 镜像:docker build -t my-springboot-app .

    1. -t:用于指定镜像名字为 my-springboot-app
    2. .:最后的句点表示 Dockerfile 文件所在的当前目录
  2. 运行容器:执行以下命令即可启动一个新容器并运行应用程序:docker run -p 8080:8080 my-springboot-app

    1. -p:用于将容器内部的 8080 端口映射到主机的 8080 端口上,这样外部就可以通过浏览器访问该应用程序了

目录挂载

现存问题

  1. 使用 Docker 运行后,我们改了项目代码不会立刻生效,需要重新 buildrun,很是麻烦
  2. 容器里面产生的数据,例如 log 文件,数据库备份文件,容器删除之后就丢失了

我们希望容器之间可以有一个数据共享的技术。Docker 容器中产生的数据,同步到本地。

目录挂载可以解决以上问题:将容器内的目录,挂载到 Linux 上面,实现容器的持久化同步操作。容器间也是可以数据共享的。

几种挂载方式:

  • bind mount:直接把宿主机目录映射到容器内,适合挂代码目录和配置文件。可挂到多个容器上
  • volume: 由容器创建和管理,创建在宿主机,所以删除容器不会丢失,官方推荐,更高效,Linux 文件系统,适合存储数据库数据。可挂到多个容器上。
  • tmpfs mount: 适合存储临时文件,存宿主机内存中。不可多容器共享。

文档参考:https://docs.docker.com/storage/

img

挂载演示:

  • bind mount 方式用绝对路径 -v D:/code:/app
  • volume 方式,只需要一个名字 -v db-data:/app

示例:docker run -p 8080:8080 --name test-hello -v D:/code:/app -d test:v1

注意:挂载后,容器里的代码就会替代你本机的代码了,如果你的代码目录没有 node_modules 目录,你需要在代码目录执行下 npm install --registry=https://registry.npm.taobao.org 确保依赖库都已经安装,否则可能会提示 “Error: Cannot find module ‘koa’”

docker run -it -v 主机目录:容器目录

# 将外部的 /home/ceshi 文件夹和容器内部的 home 文件夹链接起来,双向链接
[root@fantastic-lasers-1 /]# docker run -it -v /home/ceshi:/home centos /bin/bash

# 查看是否挂载成功
[root@fantastic-lasers-1 /]# docker inspect
f38a45b6045e

image-20230422154621795

好处:以后修改只需要在本地修改即可,容器内会自动同步!

实战:

[root@fantastic-lasers-1 /]# docker pull mysql

# 运行容器,需要做数据挂载
# 注意安装启动 mysql 是需要配置密码的
# 官方测试:
# -e: 环境配置
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动我们的容器
[root@fantastic-lasers-1 /]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql

在本地进行连接:Navicat Premium 16

image-20230422160536961

[root@fantastic-lasers-1 home]# ls
ceshi  hello.java  mysql  test.java  www
[root@fantastic-lasers-1 home]# cd mysql
[root@fantastic-lasers-1 mysql]# ls
conf  data
[root@fantastic-lasers-1 mysql]# cd data/
[root@fantastic-lasers-1 data]# ls
auto.cnf       ca.pem             ib_buffer_pool  #innodb_temp        public_key.pem   undo_002
binlog.000001  client-cert.pem    ibdata1         mysql               server-cert.pem
binlog.000002  client-key.pem     ib_logfile0     mysql.ibd           server-key.pem
binlog.index   #ib_16384_0.dblwr  ib_logfile1     performance_schema  sys
ca-key.pem     #ib_16384_1.dblwr  ibtmp1          private_key.pem     undo_001

# 在本地创建一个数据库 test,然后再在服务器端查看,也可以看到 test 文件夹
[root@fantastic-lasers-1 data]# ls
auto.cnf       ca.pem             ib_buffer_pool  #innodb_temp        public_key.pem   undo_001
binlog.000001  client-cert.pem    ibdata1         mysql               server-cert.pem  undo_002
binlog.000002  client-key.pem     ib_logfile0     mysql.ibd           server-key.pem
binlog.index   #ib_16384_0.dblwr  ib_logfile1     performance_schema  sys
ca-key.pem     #ib_16384_1.dblwr  ibtmp1          private_key.pem     test

# 即使把容器删掉,数据也不会丢失!

具名挂载和匿名挂载:

  • 匿名挂载:-v 容器内路径,不写主机地址,所有 docker 容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx,匿名挂载会随机生成一个名字
  • 具名挂载:-v 卷名:容器内路径,不同于匿名挂载,具名卷需要赋予其一个有意义的名称,其存放在 /var/lib/docker/volumes/卷名/_data 中,具名挂载可以方便地找到我们的卷,大多数情况使用
[root@fantastic-lasers-1 data]# docker run -d -P --name nginx02 -v jumping-nginx:/etc/nginx nginx
[root@fantastic-lasers-1 data]# docker volume ls
  • 指定路径挂载:-v /宿主机路径:容器内路径, 是一种将主机文件系统的目录 (绝对路径)直接挂载到容器中的方式,容器中的修改也会同时影响到主机上的文件系统,因为它们使用的是同一个文件系统。这种挂载方式的优点是,您可以轻松地将您需要的主机文件目录(例如代码或配置文件)与容器分离出来。

数据卷通信:多容器间进行数据共享–volumes-from

# 运行父容器,也称为数据卷容器
[root@fantastic-lasers-1 data]# docker run -it --name docker01 lk/centos /bin/bash
# 子容器与父容器数据共享
[root@fantastic-lasers-1 data]# docker run -it --name docker02 --volumes-from docker01 lk/centos

只要有一个容器还在用这个数据,这个数据就会一直存在!因为容器间共享的文件是一个双向拷贝的概念。

# 多个 mysql 实现数据共享和同步
[root@fantastic-lasers-1 data]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql
[root@fantastic-lasers-1 data]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volume-from mysql01 mysql

结论:

  1. 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
  2. 但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!

Docker 网络:多容器通信

理解 Docker0

  1. 清空所有容器和镜像

  2. 查看网卡

[root@fantastic-lasers-1 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP qlen 1000
    link/ether aa:aa:00:18:61:58 brd ff:ff:ff:ff:ff:ff
    inet 104.225.155.88/20 brd 104.225.159.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a8aa:ff:fe18:6158/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP qlen 1000
    link/ether ba:aa:00:18:61:58 brd ff:ff:ff:ff:ff:ff
    inet 169.254.254.254/32 brd 169.254.254.254 scope link eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::b8aa:ff:fe18:6158/64 scope link
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:75:f5:22:01 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:75ff:fef5:2201/64 scope link
       valid_lft forever preferred_lft forever

  1. 思考:docker 是如何处理容器的网络访问的?
[root@fantastic-lasers-1 ~]# docker run -d -P --name tomcat01 tomcat
[root@fantastic-lasers-1 ~]# docker exec -it tomcat01 /bin/bash
[root@fantastic-lasers-1 ~]# apt update
[root@fantastic-lasers-1 ~]# apt install -y net-tools
[root@fantastic-lasers-1 ~]# apt install -y iproute2
[root@fantastic-lasers-1 ~]# apt install -y iputils-ping

# 查看容器的内部网络地址 ip addr
[root@fantastic-lasers-1 ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
67: eth0@if68: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# 注意看这里的 67: eth0@if68

# 本机可以 ping 通容器内部
[root@fantastic-lasers-1 ~]# 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.150 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.070 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.079 ms
  1. 启动容器后再次测试:
[root@fantastic-lasers-1 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP qlen 1000
    link/ether aa:aa:00:18:61:58 brd ff:ff:ff:ff:ff:ff
    inet 104.225.155.88/20 brd 104.225.159.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a8aa:ff:fe18:6158/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP qlen 1000
    link/ether ba:aa:00:18:61:58 brd ff:ff:ff:ff:ff:ff
    inet 169.254.254.254/32 brd 169.254.254.254 scope link eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::b8aa:ff:fe18:6158/64 scope link
       valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:75:f5:22:01 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:75ff:fef5:2201/64 scope link
       valid_lft forever preferred_lft forever
68: vethc19d0bb@if67: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
    link/ether 06:09:0d:16:94:0e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::409:dff:fe16:940e/64 scope link
       valid_lft forever preferred_lft forever
# 注意看这里的 68: vethc19d0bb@if67

原理:

  1. Docker 使用的是 Linux 的桥接,宿主机中是一个 Docker 容器的网桥 docker0
  2. Docker 中的所有网络接口都是虚拟的,虚拟的转发效率高
  3. 只要安装了 Docker,就会有一个网卡 docker0,网卡使用桥接模式,使用的技术是 evth-pair 技术!
  4. 我们每启动一个 docker 容器,docker 就会给容器分配一个 ip
  5. 每多启动一个容器,主机 ip addr 就会发现多了一对网卡 veth

evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连。正因为有这个特性,evth-pair 可以充当一个桥梁,连接各种虚拟网络设备。

  1. 容器之间是可以互相 ping 通的,因为容器公用一个路由器 docker0,所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用 ip
image-20230423103147499

image-20230423103516504

思考一个问题:我们编写了一个微服务,database url=ip;项目不重启,数据库 ip 换掉了,我们希望可以处理这个问题,可以使用名字来访问容器?

[root@fantastic-lasers-1 ~]# docker run -d -P --name tomcat02 tomcat
[root@fantastic-lasers-1 ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

# 可以通过 --link 解决网络连通问题
[root@fantastic-lasers-1 ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
[root@fantastic-lasers-1 ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.128 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.112 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.121 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.075 ms

# 反向可以 ping 通吗?不能
# 查看 hosts 配置
[root@fantastic-lasers-1 ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat02 2344c7485449
172.17.0.4	6dfba96c8b71

本质探究:–link 就是我们在 hosts 配置中增加了一个 172.17.0.3 tomcat02 2344c7485449 的映射,所以可以通过容器名称 ping 通。

但是现在 Docker 已经不建议使用 –link 了

docker0 问题:不支持容器名连接访问

创建虚拟网络

# 查看所有的 docker 网络
[root@fantastic-lasers-1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
1a5a7a4c35bb   bridge    bridge    local
cbfc17931aaa   host      host      local
d38d5e451f37   none      null      local

网络模式:

  1. bridge:桥接模式(默认),自己创建的网络也属于这个模式
  2. none:不配置网络
  3. host:和宿主机共享网络
# 直接启动的命令有一个默认操作 --net bridge,这就是 docker0
[root@fantastic-lasers-1 ~]# docker run -d -P --name tomcat01 --net bridge tomcat

# 自定义网络
# 子网地址:--subnet 192.168.0.0/16
# 路由器地址:--gateway 192.168.0.1
[root@fantastic-lasers-1 ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
[root@fantastic-lasers-1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
1a5a7a4c35bb   bridge    bridge    local
cbfc17931aaa   host      host      local
46800e325ac1   mynet     bridge    local
d38d5e451f37   none      null      local
[root@fantastic-lasers-1 ~]# docker network inspect mynet

接下来我们的容器可以放在自己创建的网络当中:

[root@fantastic-lasers-1 ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
[root@fantastic-lasers-1 ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat

# 可以看到多了两个容器:192.168.0.2 | 192.168.0.3
[root@fantastic-lasers-1 ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "46800e325ac169ce2f45ccc6a08bceaf6b02d71a0fe706667f5239191a690522",
        "Created": "2023-04-23T11:51:26.548804973+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "513faa75d9ccf6c1fbf5fa54fb27199c9b52ea2c5de07035f7dbc3013f197c43": {
                "Name": "tomcat-net-01",
                "EndpointID": "b8f1bbe2d2bd5c6b961fc26490352d3caad7dd89a0951d1526a1daaea403370c",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "b2547e9f4ddaa83e0a6a975c9bab683a139688ef09942e0a058f13b2c2fdad8e": {
                "Name": "tomcat-net-02",
                "EndpointID": "9b9f58b4e46ac7be406f0678c782a697bfdaf143f74b7ea4fea31da35c1a516b",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

现在同一网络内的容器就可以互相 ping 通:

# 直接 ping ip,可通
[root@fantastic-lasers-1 ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.135 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.096 ms

# ping 名字,也可通
[root@fantastic-lasers-1 ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.104 ms

网络连通

[root@fantastic-lasers-1 ~]# docker network --help

Usage:  docker network COMMAND

Manage networks

# 注意看这个 connect:可以将一个容器连接到一个网络
Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

[root@fantastic-lasers-1 ~]# docker network connect --help

Usage:  docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network

Options:
      --alias strings           Add network-scoped alias for the container
      --driver-opt strings      driver options for the network
      --ip string               IPv4 address (e.g., "172.30.100.104")
      --ip6 string              IPv6 address (e.g., "2001:db8::33")
      --link list               Add link to another container
      --link-local-ip strings   Add a link-local address for the container
# 测试打通
[root@fantastic-lasers-1 ~]# docker network connect mynet tomcat01
[root@fantastic-lasers-1 ~]# docker network inspect mynet

# 连接之后发生了什么事情:mynet 增加了 tomcat01
"Containers": {
"8ef78a155944c263373776eac077156788617cb4521ea25cf79f11176ebb43db": {
                "Name": "tomcat01",
                "EndpointID": "b156c6ceb1b53276a0013c1d736c219e9f0b3a9aba84521c1e86bf13a76a2515",
                "MacAddress": "02:42:c0:a8:00:04",
                "IPv4Address": "192.168.0.4/16",
                "IPv6Address": ""
            },
}

# 连通之后将 tomcat01 放到 mynet 网络下
# 实现一个容器两个 ip 地址!
# 阿里云:公网 ip | 私网 ip

[root@fantastic-lasers-1 ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.201 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.087 ms

结论:假设要跨网络操作别人,就需要使用 docker network connect 连通!

实战:部署 Redis 集群

参考资料:【狂神说 Java】Redis 最新超详细版教程通俗易懂

使用 shell 脚本:

# 创建网卡
docker network create redis --subnet 172.38.0.0/16

# 通过脚本创建六个 redis 配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

# 创建集群
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

/data # redis-cli -c
127.0.0.1:6379> cluster info
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:59
cluster_stats_messages_pong_sent:58
cluster_stats_messages_sent:117
cluster_stats_messages_ping_received:53
cluster_stats_messages_pong_received:59
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:117

127.0.0.1:6379> cluster nodes
7b2ac2756ee00dcffc60242731bb763bed32a5dd 172.38.0.13:6379@16379 master - 0 1682230088000 3 connected 10923-16383
ece02c3fca507e0fae03085a0454aaca9516ab22 172.38.0.16:6379@16379 slave f93eb8be3ecfef6d3b0fd2e35ed267b15a2a7e13 0 1682230088000 6 connected
42584cb597365412818ddcc4b0924230f3830968 172.38.0.15:6379@16379 slave bb23faab8346e05118ab66e3585ac17468ef6332 0 1682230089718 5 connected
758b99cdd29a00d2fee27b76f7e7160d56cfd699 172.38.0.14:6379@16379 slave 7b2ac2756ee00dcffc60242731bb763bed32a5dd 0 1682230088715 4 connected
f93eb8be3ecfef6d3b0fd2e35ed267b15a2a7e13 172.38.0.12:6379@16379 master - 0 1682230089000 2 connected 5461-10922
bb23faab8346e05118ab66e3585ac17468ef6332 172.38.0.11:6379@16379 myself,master - 0 1682230088000 1 connected 0-5460

# 第三个节点 master
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK

# 在本机把 redis-3 停掉
[root@fantastic-lasers-1 ~]# docker stop redis-3

# 重新 get a 的值:发现现在的机器是 14,而 14 是 13 的从机,这里可以体现高可用
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"

# 13 master,fail -> 14 master
172.38.0.14:6379> cluster nodes

image-20230423141529840

使用 docker 搭建 redis 集群完成!

Docker Swarm

Docker-Compose

如果项目依赖更多的第三方软件,我们需要管理的容器就更加多,每个都要单独配置运行,指定网络。
在这节,我们使用 docker-compose 把项目的多个服务集合到一起,一键运行。

  1. 安装 Docker Compose
    1. 如果你是安装的桌面版 Docker,不需要额外安装,已经包含了。
    2. 如果是没图形界面的服务器版 Docker,你需要单独安装 安装文档
    3. 运行 docker-compose 检查是否安装成功
  2. 编写脚本:要把项目依赖的多个服务集合到一起,我们需要编写一个 docker-compose.yml 文件,描述依赖哪些服务。参考文档:https://docs.docker.com/compose/
version: "3.7"

services:
  app:
    build: ./
    ports:
      - 80:8080
    volumes:
      - ./:/app
    environment:
      - TZ=Asia/Shanghai
  redis:
    image: redis:5.0.13
    volumes:
      - redis:/data
    environment:
      - TZ=Asia/Shanghai

volumes:
  redis:
  1. 跑起来:

    1. docker-compose.yml 文件所在目录,执行:docker-compose up
    2. 命令参考:https://docs.docker.com/compose/reference/up/
  2. Docker-Compose 的其他命令:

    1. 在后台运行只需要加一个 -d 参数 docker-compose up -d
    2. 查看运行状态:docker-compose ps
    3. 停止运行:docker-compose stop
    4. 重启:docker-compose restart
    5. 重启单个服务:docker-compose restart service-name
    6. 进入容器命令行:docker-compose exec service-name sh
    7. 查看容器运行 log:docker-compose logs [service-name]

发布和部署

镜像仓库介绍

镜像仓库用来存储我们 build 出来的 “安装包”,Docker 官方提供了一个 镜像库,里面包含了大量镜像,基本各种软件所需依赖都有,要什么直接上去搜索。

我们也可以把自己 build 出来的镜像上传到 docker 提供的镜像库中,方便传播。
当然你也可以搭建自己的私有镜像库,或者使用国内各种大厂提供的镜像托管服务,例如:阿里云、腾讯云

上传我们的镜像

发布到 Docker Hub

  1. 注册一个账号

  2. 创建一个镜像库

  3. 命令行登录账号:docker login -u username

  4. 新建一个 tag,名字必须跟你注册账号一样:docker tag test:v1 username/test:v1

  5. 推上去:docker push username/test:v1

  6. 部署试下:docker run -dp 8080:8080 username/test:v1

发布到阿里云上

  1. 登录阿里云
  2. 找到容器镜像服务
  3. 创建命名空间
  4. 创建镜像仓库
  5. 浏览仓库信息

image-20230422204441268

备份和迁移数据

迁移方式介绍

容器中的数据,如果没有用挂载目录,删除容器后就会丢失数据。

  • 如果你是用 bind mount 直接把宿主机的目录挂进去容器,那迁移数据很方便,直接复制目录就好了。
  • 如果你是用 volume 方式挂载的,由于数据是由容器创建和管理的,需要用特殊的方式把数据弄出来。

备份和导入 Volume 的流程

  1. 备份:
    1. 运行一个 ubuntu 的容器,挂载需要备份的 volume 到容器,并且挂载宿主机目录到容器里的备份目录。
    2. 运行 tar 命令把数据压缩为一个文件
    3. 把备份文件复制到需要导入的机器
  2. 导入:
    1. 运行 ubuntu 容器,挂载容器的 volume,并且挂载宿主机备份文件所在目录到容器里
    2. 运行 tar 命令解压备份文件到指定目录

备份 MongoDB 数据演示

  1. 运行一个 mongodb,创建一个名叫 mongo-data 的 volume 指向容器的 /data 目录
    docker run -p 27018:27017 --name mongo -v mongo-data:/data -d mongo:4.4

  2. 运行一个 Ubuntu 的容器,挂载 mongo 容器的所有 volume,映射宿主机的 backup 目录到容器里面的 /backup 目录,然后运行 tar 命令把数据压缩打包
    docker run --rm --volumes-from mongo -v d:/backup:/backup ubuntu tar cvf /backup/backup.tar /data/

  3. 最后你就可以拿着这个 backup.tar 文件去其他地方导入了

恢复 Volume 数据演示

  • 运行一个 ubuntu 容器,挂载 mongo 容器的所有 volumes,然后读取 /backup 目录中的备份文件,解压到 /data/ 目录
    docker run --rm --volumes-from mongo -v d:/backup:/backup ubuntu bash -c "cd /data/ && tar xvf /backup/backup.tar --strip 1"
  • 注意,volumes-from 指定的是容器名字,strip 1 表示解压时去掉前面 1 层目录,因为压缩时包含了绝对路径

参考资料

  1. Docker 快速入门

  2. 官方文档 | Docker Hub

  3. 狂神说 Java: Docker 最新超详细版教程通俗易懂

标签:容器,教程,--,fantastic,lasers,使用,docker,root,Docker
From: https://www.cnblogs.com/lockegogo/p/17384574.html

相关文章

  • 【pytorch】土堆pytorch教程学习(六)神经网络的基本骨架——nn.module的使用
    torch.nn是pytorch的一个神经网络库(nn是neuralnetwork的简称)。Containerstorch.nn构建神经网络的模型容器(Containers,骨架)有以下六个:ModuleSequentialModuleListModuleDictParameterListParameterDict本博文将介绍神经网络的基本骨架——nn.module的使用。......
  • BNE0x03Simple - 内核提权 searchsploit使用
    主机发现sudonmap-sT--min-rate10000-p-xx.xx.xx.xx-oAnmapscan/ports只有一个端口开放sudonmap-sT-sV-sC-O-pxx.xxx.xx.xx-oAnmapscan/detailsudonmap-sU--top-ports20xx.xx.xx.xx-oAnmapscan/udpsudonmap--script=vuln-pxx.xx.xx.xx-oAnma......
  • (转)Offline List 使用教程
    OfflineList使用教程一、OfflineList基本介绍管理工具说简单点就是用来整理自己roms的工具,OfflineList由于界面直观,操作简单比较受欢迎。最新版是v0.7.3beta2,下载地址:http://offlinelist.free.fr/是依靠crc和size进行校验的本文由电玩盒子收集整理,转载请注明出处:ht......
  • A100服务器使用过程的曲折
    使用A100显卡跑程序时,当使用多张卡一起跑的时候就会出现程序卡住不动的情况,这是由于系统的BIOS里IO虚拟化默认启动了PCI访问控制服务(ACS)导致GPU间无法直接通过P2P方式通信exportNCCL_P2P_DISABLE=1在代码程序前加上这个命令就能多卡运行了、......
  • httprunner 4.x学习 - 7.环境变量.env 的使用
    前言一般来说,在进行实际应用的开发过程中,应用会拥有不同的运行环境,通常会有以下环境:本地开发环境测试环境生产环境在不同环境中,我们可能会使用不同的数据库或邮件发送等配置,这时候则需要通过.env文件来针对不同的运行环境作不同的设置。环境变量基础知识在自动化测试中......
  • macOS下使用VS Code配置C/C++开发环境
      macOS系统中默认的C/C++编译器是clang/clang++,命令行使用gcc/g++或者clang/clang++来执行命令时,都是调用clang/clang++编译器,想使用gcc/g++编译器结合VSCode进行开发的话,我们可以自己安装。查看一下gcc和clang   1.安装Homebrew,官网链接,复制粘贴到Terminal运行脚......
  • PHP trait使用
    一、trait、继承、实例化三者的区别对于当前一个类需要用到另一个或多个类的方法的情况,我们一般会想到的方式有继承、直接实例化另外一个或多个类等等的方法,来对比一下这些方法和Trait类的区别:继承:对于继承,可以完美地复用另一个类的一些方法,但是对于需要复用多个类的方法时,PHP......
  • 使用 Sa-Token 完成踢人下线功能
    一、需求在企业级项目中,踢人下线是一个很常见的需求,如果要设计比较完善的话,至少需要以下功能点:可以根据用户userId踢出指定会话,对方再次访问系统会被提示:您已被踢下线,请重新登录。可以查询出一个账号共在几个设备端登录,并返回其对应的Token凭证,以便后续操作。可以只踢出......
  • Android Studio中使用断点调试程序
    1.设置断点在希望中断的位置左边label一下,设置一个断点。例如下方图片所示在ActivityResultRegistry类中的第147行设置了一个断点,以及在365行dispatchResult()方法处设置了一个断点。设置好断点后,可以在菜单栏依次点击Run->ViewBreakpoints查看所设置的全部的断点,并进行删减......
  • [PLC]三菱FX5U WORKS3中使用特殊继电器/特殊寄存器注释显示
    1.菜单栏"视图"-->"多个注释"-->"注释读取"2.勾选如图所示:3.点击确定,例如sm412这种特殊继电器/特殊寄存器就会自动显示注释.......