Docker入门这一篇就够了

文章目录

一、概述

1. 什么是Docker

docker是一个开源的应用容器引擎,基于go语言开发并遵循了apache2.0协议开源。

docker可以让开发者打包他们的 应用 以及 依赖包 到一个轻量级、可移植的容器中,然后发布到任何流行的linux服务器,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类iphone的app),并且容器开销极其低。

2. 容器化技术与虚拟机技术的区别

  1. 虚拟机(virtual machine)就是带环境安装的一种解决方案 。

    它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。

    在这里插入图片描述
    虚拟机的缺点:资源占用多、冗余步骤多、启动慢。

  2. 由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为LXC)。

    Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。

    在这里插入图片描述

比较了容器技术和虚拟机技术的不同之处:

  1. 传统虚拟机技术,虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程。

  2. 而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

  3. 每个容器之间互相隔离,每个容器有自己的文件系统,容器之间进程不会相互影响,能区分计算资源。

3. Docker的优势

官方的话:

  • 灵活:即使是最复杂的应用也可以集装箱化。
  • 轻量级:容器利用并共享主机内核。
  • 可互换:您可以即时部署更新和升级。
  • 便携式:您可以在本地构建,部署到云,并在任何地方运行。
  • 可扩展:您可以增加并自动分发容器副本。
  • 可堆叠:您可以垂直和即时堆叠服务。

4. Docker的架构

在这里插入图片描述

  1. Client(客户端):通过一些命令与 Docker 服务器作交互,比如说 docker build:构建一个容器;docker pull:接取一个容器;docker run:运行一个容器

  2. Docker_host(服务器):Docker 的操作都在这里执行

    1. Docker daemon(守护进程):Docker架构中的主体部分

      1. 提供 Server 的功能使其可以接受 Docker Client 的请求
      2. 当需要容器镜像时,则从Registry中下载镜像
    2. Images(镜像):docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

    3. Containers(容器):Docker 利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。(初学者可以暂时把这个容器理解为就是一个简易的linux)

      可以把镜像理解成是 java 中的类,而容器理解成 java 中的对象实例,一个类可以拥有多个对象实例

  3. Register(远程仓库):存放镜像的地方,分为公有仓库和私有仓库

二、安装Docker

这部分可以参照官方文档:https://docs.docker.com/get-docker/,根据自己的系统去进行安装,我这里使用的系统是 Centos 7

在 Centos 系统上安装 Docker,这部分在官方文档的位置(其它Linux发行版安装方法也在这):https://docs.docker.com/engine/install/centos/

1. 服务器有网络时

  1. 卸载旧版本

    yum remove docker \
                      docker-client \
                      docker-client-latest \
                      docker-common \
                      docker-latest \
                      docker-latest-logrotate \
                      docker-logrotate \
                      docker-engine
    
  2. 需要的安装包

    yum install -y yum-utils
    
  3. 设置存储库

    # 官方给的代码,存储库是国外的,下载慢
    yum-config-manager \
        --add-repo \
        https://download.docker.com/linux/centos/docker-ce.repo
    
    # 推荐使用阿里云的镜像仓库
    yum-config-manager \
        --add-repo \
        http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
  4. 安装 Docker 引擎
    docker-ce:ce表示社区版,还有个ee,表示企业版

    # 安装前可以先更新软件包索引(非必须)
    yum makecache fast
    
    # 安装最新版的 Docker 引擎,包括docker社区版,docker社区版客户端等
    yum install docker-ce docker-ce-cli containerd.io
    
  5. 启动 Docker

    systemctl start docker
    
  6. 测试是否成功安装 Docker

    # 查看 Docker 的版本号
    docker version
    

    出现下图则说明安装成功:
    在这里插入图片描述

  7. 测试下载 hello-world 镜像

    docker run hello-world
    

    在这里插入图片描述

  8. 查看下载的 hello-world 镜像

    docker images
    
  9. 卸载 Docker

    # 卸载Docker Engine,CLI等
    yum remove docker-ce docker-ce-cli containerd.io
    
    # 主机上的镜像,容器,等文件不会自动删除,需要手动删除
    # /var/lib/docker docker的默认工作路径
    rm -rf /var/lib/docker
    

2. 配置阿里云镜像加速

  1. 登录阿里云(https://www.aliyun.com/),找到容器镜像服务:
    在这里插入图片描述
  2. 如果没有开通的话,就跟着阿里云的步骤开通一下。
  3. 找到最下面的镜像加速器,选择自己对应的系统,跟着步骤一步一步走就 ok 了

在这里插入图片描述

3. 服务器无网络时

这部分可以参照官方文档:从二进制文件安装Docker Engine

下面安装过程是在rhel7.3系统上进行的

  1. 安装依赖包:

    yum install -y yum-utils device-mapper-persistent-data lvm2
    
  2. 查看自己服务器的架构:

    uname -a
    

    我的是x86 64位的:
    在这里插入图片描述

  3. 然后要下载好docker的二进制安装文件压缩包,地址:https://download.docker.com/linux/static/stable/

    根据第二步查出的架构,选择相应架构下的压缩包,版本自己选择,我这里下载的是:x86_64/docker-19.03.9.tgz

  4. 拷贝压缩包到机器中并解压:

    tar xzvf docker-19.03.9.tgz
    
  5. 将解压好的文件拷贝到/usr/bin/目录下:

    cp docker/* /usr/bin/
    
  6. 启动Docker守护程序:

    dockerd &
    
  7. 测试docker是否安装成功:docker version

    如下则说明安装成功:
    在这里插入图片描述

4. 配置文件 daemon.json

docker安装后默认没有 daemon.json 这个配置文件,需要进行手动创建。配置文件的默认路径:/etc/docker/daemon.json

官方的配置地址: https://docs.docker.com/engine/reference/commandline/dockerd/#options
这个博客对一些配置进行了解释:docker配置文件docker-daemon.json详解

我用到的一些配置:

{
	"registry-mirrors": ["http://harbor.test.com"], #镜像加速地址

	# 这样配置,容器的日志文件会放到 /var/log/containers 目录下,就可以用EFK搜索出来对应的信息了
	"exec-opts": ["native.cgroupdriver=systemd"], # Centos中默认是有两个,这里统一使用systemd
	"log-driver": "json-file",	# 存储日志的类型
	"log-opts": {
		"max-size": "100m" # 限制日志的大小
	},
	"insecure-registries": ["https://hub.zyx.com"] # 配置私有仓库地址
}

修改完后,需要下面两个步骤使新的配置生效

# reload配置文件
systemctl daemon-reload

# 重启docker
systemctl restart docker

三、Docker常用命令

官方文档:Docker的所有命令:https://docs.docker.com/reference/

在这里插入图片描述

1. 查看信息

1. docker --help(帮助信息)

命令说明
docker --help查看全部命令
docker 命令 --help查看某个命令的帮助信息

2. docker info(详细信息)

命令说明
docker info显示docker的系统信息,包括镜像和容器的数量

3. docker version(版本信息)

命令说明
docker version打印docker版本信息

2. 镜像命令

1. docker images(查看镜像)

  • 命令:docker images [OPTIONS] [REPOSITORY[:TAG]]

  • 常用可选项:

    名称,速记默认描述
    --all , -a列出所有镜像(默认隐藏中间镜像)
    --quiet , -q只显示镜像的ID
  • 例子:

    [root@localhost ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    hello-world         latest              bf756fb1ae65        5 months ago        13.3kB
    
    • 解释
      • REPOSITORY:镜像的仓库源(名字)
      • TAG:镜像的标签(版本)
      • IMAGE ID:镜像的 id
      • CREATED:镜像的创建时间
      • SIZE:镜像的大小

2. docker search(在仓库中搜索镜像)

  • 命令:docker search [OPTIONS] TERM

  • 常用可选项:

    名称,速记默认描述
    --filter , -f根据提供的条件过滤输出,格式为key=value对。
    如果有多个过滤器,则传递多个标志
    (例如--filter is-automated=true --filter stars=3
  • 例子:

    docker search --filter stars=3 busybox
    
    NAME                 DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    busybox              Busybox base image.                             325       [OK]
    

3. docker pull(下载镜像)

  • 命令:docker pull [OPTIONS] NAME[:TAG|@DIGEST]
    如果不写 tag(版本),默认就是 latest

  • 例子:

    # 拉取最新版,下面的命令相当于: docker pull mysql:latest
    docker pull mysql
    
    # 拉取指定版本,需要确定在仓库中存在该版本
    docker pull mysql:5.7
    

4. docker rmi(删除镜像)

  • 命令:docker rmi [OPTIONS] IMAGE [IMAGE...]
    可以删除一个或多个镜像,可以通过镜像的名字或者 id 删除

  • 常用可选项:

    名称,速记默认描述
    --force , -f强制删除图像
  • 例子:

    # 删除指定镜像
    docker rmi -f e73346bdf465
    
    # 删除所有的镜像
    docker rmi -f $(docker images -aq)
    

5. docker commit(通过容器生成镜像)

  • 命令:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

  • 常用可选项:

    名称,速记默认描述
    -m指定提交的说明信息
    -a提交的镜像作者
    -c使用 Dockerfile 指令来创建镜像
    -p在 commit 时,将容器暂停
  • 例子:

    # 对一个tomcat容器进行了修改后(webapps文件中添加了app),其中7e119b82cff6表示一个容器
    docker commit -a "xiaoMaNong" -m "add webapps app" 7e119b82cff6 tomcat:v01
    
    # 然后查看本地的镜像,可以发现看到刚提交的镜像
    docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    tomcat              v01                 37af1236adef        15 seconds ago      652 MB
    

6. docker save/load(镜像的打包与加载)

  • docker save:将一个或多个镜像保存到 tar 存档(默认情况下流式传输到STDOUT)

    • 命令:docker save [OPTIONS] IMAGE [IMAGE...]

    • 常用可选项:

    名称,速记默认描述
    --output , -o写入文件,而不是STDOUT
  • docker load:从 tar 存档或STDIN加载图像

    • 命令:docker load [OPTIONS]

    • 常用可选项:

    名称,速记默认描述
    --input , -i从 tar 存档文件而非 STDIN 中读取
  • 例子:

    # 将镜像保存到本地 tar 文件
    docker save -o mysql5.7 mysql:5.7
    
    # 另一台服务器上无外网,将上面保存的 tar 包发送到该服务器,然后加载
    sudo docker load -i mysql5.7
    

3. 容器命令

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

1. docker run(新建容器并启动)

  • 命令:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

  • 常用可选项:

    名称,速记默认描述
    --name="Name"为容器分配一个名称,名称是唯一的,可以用名称来确定容器
    --detach , -d后台方式运行
    -it使用交互方式运行,进入容器查看内容
    --rm退出时自动删除容器
    --publish , -p将容器的端口发布到主机,使用方法:
    -p ip:主机端口:容器端口
    -p 主机端口:容器端口(常用)
    -p 容器端口
    容器端口
    --publish-all , -P将容器的端口随机分配到主机的空闲端口上,可以使用docker ps -a 查看
    --volume, -v绑定挂载目录,使用方法:-v /本地目录:容器目录
    匿名挂载:-v 容器目录
    具名挂载:-v 卷的名字:容器目录
    (详见 四、容器数据卷)
    --netbridge将容器连接到一个网络中,不指定会以桥接的方式连接到 docker0
    –restart=always设置容器自启动,docker 服务重启后容器也跟着重启
  • 例子:

    在这里插入图片描述

设置容器自启动

在运行 docker 容器时可以加如下参数来保证每次 docker 服务重启后容器也自动重启:

docker run --restart=always

如果容器已经启动了则可以使用如下命令:

docker update --restart=always <CONTAINER ID>
后台启动容器的坑

当以后台运行的方式启动了一个容器后,再使用 docker ps 命令发现,容器并没有在运行

[root@localhost ~]# docker run --name="centos_test" -d centos
1f38528aade344433c9d9c0b35125e3ea8007380e599c7b4a875944599481d30
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
  • 原因:docker 容器使用后台运行,就必须要有一个前台进程,如果 docker 发现没有应用,就会自动停止。
  • 解决方法:docker run -dit centos /bin/bash
    • 添加-it 参数交互运行
    • 添加-d 参数后台运行
    • 这样就能启动一个一直停留在后台运行的Centos了
    • 注意:进入容器的方法要使用exec,不要使用attach命令,attach命令就是使用现有终端,如果你要退出容器操作,那么bash结束,容器也就退出了

2. docker ps(列出容器)

  • 命令:docker ps [OPTIONS]
    不加任何参数默认显示为正在运行的容器

  • 常用可选项:

    名称,速记默认描述
    --all , -a显示所有容器
    --last , -n=?-1显示n个最后创建的容器(包括所有状态)
    --quiet , -q仅显示数字ID
  • 例子:

    [root@localhost /]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
    6097bc8e3852        centos              "/bin/bash"         10 minutes ago      Exited (0) 9 minutes ago                       sad_lamport
    ea55e44464ae        bf756fb1ae65        "/hello"            3 hours ago         Exited (0) 3 hours ago                         unruffled_chandrasekhar
    
    • 解释:
      • CONTAINER ID:容器id
      • IMAGE:镜像
      • COMMAND:引用命令
      • CREATED:创建容器的时间
      • STATUS:容器状态
      • PORTS:暴露的端口
      • NAMES:容器名称

3. exit/Ctrl + P + Q(退出容器)

docker run -it name 进入容器之后,使用如下的命令退出容器
exit:容器停止并退出
Ctrl + P + Q容器不停止退出

4. docker rm(删除容器)

  • 命令:docker rm [OPTIONS] CONTAINER [CONTAINER...]
    命令中的 CONTAINER 用容器的 id/name

  • 常用可选项:

    名称,速记默认描述
    --force , -f强制删除正在运行的容器(使用SIGKILL)
  • 例子:

    # 删除所有的容器
    docker rm -f $(docker ps -aq)
    docker ps -aq | xargs docker rm -f
    

5. docker start/stop(启动和停止容器)

docker start 容器id/name		# 启动容器
docker restart 容器id/name	# 重启容器
docker stop 容器id/name		# 停止当前运行的容器
docker kill 容器id/name		# 强制停止运行的容器

6.docker exec(进入当前正在运行的容器(打开新终端))

  • 命令:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

  • 常用可选项:

    名称,速记默认描述
    -it以交互模式运行
  • 例子:

    docker exec -it centos1 /bin/bash
    

7. docker attach(进入当前正在运行的容器(进入容器启动命令的终端,不会启动新的线程))

  • 命令:docker attach [OPTIONS] CONTAINER

8. docker cp(在容器和本地文件系统之间复制文件/文件夹)

  • 命令:

    # 在本地系统执行
    
    # 将容器中的文件拷贝到本地文件系统中
    docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
    
    # 将本地系统文件拷贝到容器中
    docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
    

9. docker top(查看容器中进程信息)

# 类似于 linux 中的 top 命令
docker top CONTAINER

10. docker logs(日志信息)

  • 命令:docker logs [OPTIONS] CONTAINER

  • 常用可选项:

    名称,速记默认描述
    --follow , -f跟踪日志输出
    --tailall从日志末尾开始显示的行数
    --timestamps , -t显示时间戳
  • 例子:

# 显示全部日志
docker logs -ft centos_test

# 显示10条日志
docker logs -ft --tail 10 centos_test

11. docker inspect(返回容器详细信息)

docker inspect CONTAINER

例子(标注了常用的信息):

[root@localhost ~]# docker inspect c2b030acf83a
[
    {
        "Id": "c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6",//容器id,一般使用的是前12位
        "Created": "2020-06-07T15:04:33.788916436Z",//容器创建时间
        "Path": "/bin/bash",	//默认控制台
        "Args": [],	//传递的参数
        "State": {	//容器的状态
            "Status": "running",	//running 表示正在运行
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 101264,	//进程id
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-06-07T15:04:35.115091831Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee",//镜像的id
        "ResolvConfPath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/hostname",
        "HostsPath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/hosts",
        "LogPath": "/var/lib/docker/containers/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6/c2b030acf83a23b33471b28d58e20d96f9eb22fceab5ffb9b0a848841a3045b6-json.log",
        "Name": "/zyx",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {	// 主机的配置
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Capabilities": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90-init/diff:/var/lib/docker/overlay2/02399b4c6980e3092721d60619f83c651885c0b0eb1241a6417f0bddb44b5463/diff",
                "MergedDir": "/var/lib/docker/overlay2/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90/merged",
                "UpperDir": "/var/lib/docker/overlay2/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90/diff",
                "WorkDir": "/var/lib/docker/overlay2/bbe44f663e7c732f43fa3a35633008e8d7027fed9d41400a1aa970d5bdf45c90/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],	//数据卷挂载
        "Config": {		//基本配置
            "Hostname": "c2b030acf83a",		//容器名字
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [	//基本的环境变量
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20200114",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-01-14 00:00:00-08:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS"
            }
        },
        "NetworkSettings": {	//网络的一些设置
            "Bridge": "",
            "SandboxID": "70097fb845389da1a20faf75eabb2f84866ba4b38ea8388397a840b9a344aa85",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/70097fb84538",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "cb235799991b3c585bf97ea5fcdfc7a069aa13554a5f84ea35e6172c9cad2ed5",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {		//桥接
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "020a4fab0d00a01941b764d9f16740807b2c2673b8138d7e1ece968086b5475b",
                    "EndpointID": "cb235799991b3c585bf97ea5fcdfc7a069aa13554a5f84ea35e6172c9cad2ed5",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

12. docker stats(监控容器资源消耗)

  • 命令:docker stats [OPTIONS] [CONTAINER...]
  • 常用可选项:
    名称,速记默认描述
    --all, -a默认仅显示运行中的容器显示所有容器
    --format string格式化输出
    --no-stream只返回当前的状态

例子:

# 查看当前运行中的所有容器资源
> docker stats
CONTAINER ID   NAME                            CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O         PIDS
fdedc094cd26   dockercompose_nginx_1           0.00%     2.148MiB / 3.696GiB   0.06%     4.86MB / 4.78MB   0B / 0B           3
68189b6d290f   dockercompose_kibana_1          0.00%     413.7MiB / 3.696GiB   10.93%    125MB / 96.4MB    263MB / 113MB     22
22ed88ee3afa   dockercompose_elasticsearch_1   0.39%     524.9MiB / 3.696GiB   13.87%    133MB / 252MB     72.4MB / 2.85MB   62

# 格式化为 json
> docker stats --no-stream --format "{\"container\":\"{{ .Container }}\",\"memory\":{\"raw\":\"{{ .MemUsage }}\",\"percent\":\"{{ .MemPerc }}\"},\"cpu\":\"{{ .CPUPerc }}\"}"
{"container":"fdedc094cd26","memory":{"raw":"2.148MiB / 3.696GiB","percent":"0.06%"},"cpu":"0.00%"}
{"container":"68189b6d290f","memory":{"raw":"413.8MiB / 3.696GiB","percent":"10.93%"},"cpu":"0.45%"}
{"container":"22ed88ee3afa","memory":{"raw":"525.1MiB / 3.696GiB","percent":"13.87%"},"cpu":"0.94%"}

结果说明:

默认情况下,stats 命令会每隔 1 秒钟刷新一次输出的内容直到你按下 ctrl + c。下面是输出的主要内容:

字段说明
CONTAINER以短格式显示容器的 ID。
CPU %CPU 的使用情况。
MEM USAGE / LIMIT当前使用的内存和最大可以使用的内存。
MEM %以百分比的形式显示内存使用情况。
NET I/O网络 I/O 数据。
BLOCK I/O磁盘 I/O 数据。
PIDSPID 号。

自定义的格式中可以使用的所有占位符:

点位符说明
.Container根据用户指定的名称显示容器的名称或 ID
.Name容器名称
.ID容器 ID
.CPUPercCPU 使用率
.MemUsage内存使用量
.NetIO网络 I/O
.BlockIO磁盘 I/O
.MemPerc内存使用率
.PIDsPID 号

四、数据卷

在这里插入图片描述
数据卷(Data Volumes):就是将容器内数据直接映射到本地主机环境的指定文件目录之中,可以理解为容器挂载一个虚拟数据卷然后映射到一个主机目录中

在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着容器的结束而结束),就需要将数据从宿主机挂载到容器中。

1. 挂载的类型

(1)volume(最常用)

分为匿名挂载和具名挂载:

  • 匿名挂载:-v 容器内路径

    docker run -v /ect/nginx nginx
    
  • 具名挂载:-v 卷名字:容器内路径

    docker run -v nginxConfig:/ect/nginx nginx
    

在这里插入图片描述
可以通过 docker inspect 容器名 或者 docker volume inspect 卷名 来查看到挂载信息:

"Mounts": [
      {
          "Type": "volume",		//挂载的类型
          "Name": "nginxConfig",//卷的名字
          "Source": "/var/lib/docker/volumes/nginxConfig/_data",//卷在本地的位置(这种方式挂载的卷位置默认都在/var/lib/docker/volumes/_data目录下)
          "Destination": "/ect/nginx",//容器内目录
          "Driver": "local",
          "Mode": "z",
          "RW": true,	//支持读写
          "Propagation": ""
      }
  ],

(2)bind(较常用)

使用方法:-v /本地目录:容器目录

docker run -v /home/test:/home centos

当本地不存在 /home/test 目录时,Docker 会自动创建

在这里插入图片描述

可以通过 docker inspect 容器名 来查看到挂载信息:

"Mounts": [
    {
        "Type": "bind",		//挂载的类型
        "Source": "/home/test",	//本地目录
        "Destination": "/home",	//容器内目录
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],

但是,bind 在不同的宿主机系统时不可移植的,比如WindowsLinux的目录结构是不一样的,bind 所指向的host目录也不能一样。这也是为什么bind 不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。

2. docker volume(卷管理命令)

# docker volume volume_name // 创建一个自定义容器卷
# docker volume ls // 查看所有容器卷
# docker volume inspect volume_name // 查看指定容器卷详情信息
# docker volume rm volume_name // 删除自定义数据卷

3. 权限

  • roreadonly,表示只读,表示这个路径只能通过本地去访问,容器内部是无法访问的

    docker run -d -P --name nginx01 -v /ect/nginx:ro nginx
    
  • rwreadwrite,表示可读可写,默认。

    docker run -d -P --name nginx01 -v /ect/nginx:rw nginx
    

4. 数据卷容器(–volumes-from)

数据卷容器(Data Volume Containers):用专门的容器来挂载数据卷,其他容器通过挂载这个父容器来实现数据共享,这个专门挂载数据卷的容器就是数据卷容器,简单的总结就是有一个容器来专门管理数据的持久化和容器之间数据共享
在这里插入图片描述

如果我们经常需要多个容器之间进行数据共享,我们需要用到命令 “--volumes-from

具体实例:

  1. 我们从仓库拉一个 centos 的容器镜像

    docker pull centos
    
  2. 然后运行这个镜像,创建 mycentos 容器,并创建一个数据卷挂载到 /mydata

    docker run -it -v /mydata --name mycentos centos
    
  3. 再运行两个容器,在这两个容器中使用 --volumes-from 来继承 mycentos 容器中的数据卷

    docker run -it --volumes-from mycentos --name soncentos1 centos
    
    docker run -it --volumes-from mycentos --name soncentos2 centos
    

    此时,容器 soncentos1 和 soncentos2 都挂载同一个数据卷到相同的 /mydata 目录。三个容器任何一方在该目录下的写入数据,其他容器都可以看到。

    --volumes-from 后面的容器(mycentos)就是数据卷容器。可以通过数据卷容器创建多个子容器(soncentos1,soncentos2),即便是删除了初始的数据卷容器 mycentos,或是删除了其它容器,但只要是有容器在使用该数据卷,那么它里面的数据就不会丢失!(除非是没有容器在使用它们)

五、网络

1. docker0

通过 ip addr 命令可以看到,docker 会生成一个网卡 docker0
在这里插入图片描述
每启动一个 docker 容器,docker 就会给容器分配一个 ip,默认使用桥接模式,使用的技术是 veth-pair

启动一个 redis 容器,可以看到主机上多了一个网卡,并与容器内网卡对应
容器内网卡:
在这里插入图片描述
主机网卡:
在这里插入图片描述

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

不同容器是可以互相访问的,docker0 可以理解为一个路由器

容器删除,对应的网卡也会被删除

2. docker network

ls:查看网络

docker 默认有三个网络:
在这里插入图片描述

create:创建网络

创建自定义网络,如果不指定类型,默认创建类型为 bridge 类型

  • 命令:docker network create [OPTIONS] NETWORK
名称,速记默认描述
-d, --driverbridge指定网络类型
–subnet表示网段的CIDR格式的子网
–gateway网关
  • 例子:
    1. 创建自定义网络

      docker network create -d bridge --subnet  192.168.0.0/16 --gateway 192.168.0.1 mynet
      
    2. 启动容器并使用 --net 加入网络

      docker run -d -P --name redis-net-01 --net mynet  redis:alpine
      docker run -d -P --name redis-net-02 --net mynet  redis:alpine
      
    使用 docker network inspect mynet 可以看到两个容器已经加入了该网络:
    在这里插入图片描述
    在 mynet 网络中,容器之间可以通过容器名来相互访问
    在这里插入图片描述

其它命令

可以通过 --help 来查看详细操作(例如:docker network disconnect --help

命令说明
connect将容器加入网络
disconnect容器从网络中断开连接
inspect查看网络的详细信息
prune删除所有未使用的网络
rm删除网络

3. 网络隔离

docker 中的网络中相互隔离的,这样做的好处就是,不同的集群使用不同的网络,保证集群是安全和健康的。

两个网络中的容器是隔开的,无法互相访问,通过 docker network connect 来使 A 网络中的容器加入 B 网络,从而实现 A 网络中的容器对 B 网络的访问。原理:在容器中新增一个 B 网络的 IP,即一个容器,多个 IP

六、DockerFile

1. 基础知识

这部分参考:Docker学习笔记(五)–dockerfile

  1. 每个保留关键字(指令)都是必须是大写字母

  2. Dockerfile 文件执行从上到下顺序执行

  3. # 表示注释

  4. 每一个指令都会创建提交一个新的镜像层,并提交

  5. Docker 镜像是由特殊的文件系统叠加而成;最底端是 bootfs,并使用宿主机的 bootfs。一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器。如下图

    在这里插入图片描述

2. 基础命令

关键字作用备注
FROM指定基础镜像指定dockerfile基于那个image构建,一切从这里开始
MAINTAINER作者信息用来标明这个dockerfile谁写的,一般为:姓名 + 邮箱
LABEL标签用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看
RUN执行命令执行一段命令,默认是/bin/sh 格式:RUN command 或者 RUN ["command" , "param1","param2"]
CMD容器启动命令提供启动容器时候的默认命令,和ENTRYPOINT配合使用。格式 CMD command param1 param2 或者 CMD ["command", "param1", "param2"]。可以使用 && 在一个 CMD 中拼接多个命令
ENTRYPOINT入口一般在制作一些执行就关闭的容器中会使用,格式ENTRYPOINT ["command", "param1", "param2"]
COPY复制文件build的时候复制文件到image
ADD添加文件build的时候添加文件到image中,不仅仅局限于当前build上下文,可以来源于远程服务,如果是压缩文件,会自动解压
ENV环境变量build的时候设置环境变量,可以在启动的容器的时候,通过-e覆盖。格式ENV name=value
ARG构建参数构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数
VOLUME定义外部可以挂载的数据卷指定buildimage哪些目录可以启动的时候挂载到文件系统中。启动容器的时候使用 -v 绑定 格式 VOLUME [“目录”]
EXPOSE暴露端口定义容器运行的时候监听的端口,启动容器的使用-p来绑定暴露端口。格式:EXPOSE 8080 或者 EXPOSE 8080/udp
WORKDIR工作目录指定容器内部的工作目录,如果没有创建则自动创建,如果指定 / 使用的是绝对地址;如果不是 / 开头那么是在上一条workdir的路径的相对路径
USER指定执行用户指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户
HEALTHCHECK健康检查指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制
ONBUILD触发器当存在ONBUILD关键字的镜像被继承时,当执行FROM完成之后,会执行 ONBUILD的命令,但是不影响当前镜像
STOPSIGNAL发送信号量到宿主机该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。
SHELL指定执行脚本的shell指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell

3. docker build(构建镜像)

首先要先写好 Dockerfile 文件,然后使用 docker build 命令来构建镜像

  • 命令:docker build [OPTIONS] PATH

  • 常用可选项:

    名称,速记默认描述
    -f指定要使用的Dockerfile路径。如果文件为当前目录下的 Dockerfile(文件名叫这个),则可以不用使用 -f 指定
    --tag, -t镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
  • 例子,对官方的 centos 进行修改(加入 vim 和 net-tools),构建自己的centos:

    • 先写好 dockerfile 文件:docker hub 中 99% 的镜像都是从 scratch(FROM scratch)基础镜像开始的,然后再配置需要的软件和一些配置进行构建的。这里直接从 centos 开始构建,文件名字叫 mydockerfile-centos

      FROM centos
      MAINTAINER xiaomanong<zyx1260168395>
      
      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
      
    • 使用 docker build 命令构建镜像

      # 不要忘了最后一个点 '.' ,表示当前路径
      docker build -f mydockerfile-centos -t mycentos:0.1 .
      
    • 然后使用 docker images 便可以查看到自己的镜像

4. docker history(查看镜像的创建历史)

  • 命令:docker history [OPTIONS] IMAGE

  • 常用可选项:

    名称,速记默认描述
    -Htrue以可读的格式打印镜像大小和日期
  • 例子:查看 5.3 中刚创建的 mycentos:

# 显示的构建过程是自下而上的
[root@localhost zyx]# docker history mycentos
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
f006331eed43        4 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B                  
844dae209483        4 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
9047ac00cd0f        4 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
9052f658149b        4 minutes ago       /bin/sh -c #(nop)  EXPOSE 80                    0B                  
216accbf3204        4 minutes ago       /bin/sh -c yum -y install net-tools             22.8MB              
f036dff75a56        4 minutes ago       /bin/sh -c yum -y install vim                   57.2MB              
86e8dcdb7221        5 minutes ago       /bin/sh -c #(nop) WORKDIR /usr/local            0B                  
58fa1de6f554        5 minutes ago       /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B                  
613d715c859b        5 minutes ago       /bin/sh -c #(nop)  MAINTAINER xiaomanong<zyx…   0B                  
470671670cac        5 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           5 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           5 months ago        /bin/sh -c #(nop) ADD file:aa54047c80ba30064…   237MB               

5. CMD 与 ENTRYPOINT 的区别

  • CMD:指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代
  • ENTRYPOINT:指定这个容器启动时要运行的命令,可以追加命令

首先,这里有两个 dockerfile 分别构建成的镜像:

  • 镜像 cmdtest

    FROM centos
    CMD ["ls","-a"]
    
  • 镜像 enttest

    FROM centos
    ENTRYPOINT ["ls","-a"]
    

然后使用 docker run 命令分别创建这两个镜像的容器:

  • 对镜像 cmdtest 做测试:

    # 1. 不加命令运行,会执行 dockerfile 中的 CMD 命令
    [root@localhost zyx]# docker run --rm cmdtest
    .
    ..
    
    # 2. 加上命令后,会替换 dockerfile 中默认的 CMD 命令
    [root@localhost zyx]# docker run --rm cmdtest ls -al
    total 56
    drwxr-xr-x.   1 root root 4096 Jun 16 14:30 .
    drwxr-xr-x.   1 root root 4096 Jun 16 14:30 ..
    
    # 3. 如果是对 CMD 命令添加参数,则会报错
    [root@localhost zyx]# docker run --rm cmdtest -l
    docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
    
  • 对镜像 enttest 做测试:

    # 1. 不加命令运行,会执行 dockerfile 中的 ENTRYPOINT 命令,与 CMD 效果相同
    [root@localhost zyx]# docker run --rm enttest
    .
    ..
    
    # 2. 由于 ENTRYPOINT 是追加命令,启动容器时实际执行的命令为:ls -a ls -al,故报错
    [root@localhost zyx]# docker run --rm enttest ls -al
    ls: cannot access 'ls': No such file or directory
    
    # 3. 启动容器时实际执行的命令:ls -a -l
    [root@localhost zyx]# docker run --rm enttest -l
    total 56
    drwxr-xr-x.   1 root root 4096 Jun 16 14:28 .
    drwxr-xr-x.   1 root root 4096 Jun 16 14:28 ..
    

6. 实战:使用自己的Tomcat压缩包来制作Tomcat镜像

这里使用的是自己的 Tomcat 压缩包和JDK8 压缩包来制作 Tomcat 镜像

  1. 首先将这两个压缩包发送到服务器上,然后在同一目录下编写 Dockerfile 文件:

    FROM centos
    MAINTAINER xiaomanong<zyx1260168395>
    
    ADD jdk-8u121-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.0.M26.tar.gz /usr/local/
    
    RUN yum -y install vim
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_121
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.0.M26
    ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.0.M26
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    EXPOSE 8080
    
    CMD /usr/local/apache-tomcat-9.0.0.M26/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.0.M26/logs/catalina.out
    
  2. 构建镜像:

    docker build -f  Dockerfile -t mytomcat .
    
  3. 启动一个该镜像的容器,使用 -v 来挂载目录:

    docker run -d -p 8080:8080 -v /home/test/mytomcat/webapps:/usr/local/apache-tomcat-9.0.0.M26/webapps -v /home/test/mytomcat/logs:/usr/local/apache-tomcat-9.0.0.M26/logs --name mytomcat mytomcat
    

7. 发布镜像到docker hub

(1)登录 ducker hub

ducker hub 上注册自己的账号,然后通过命令行来登录 docker hub

  • 命令:docker login [OPTIONS] [SERVER]
  • 常用可选项:
    名称,速记默认描述
    --password , -p密码
    --username , -u用户名
(2)docker tag 标记镜像
  • 命令:docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
    注意TARGET_IMAGE 格式,如下图(要使用自己 docker hub 的用户名,不然会报错):
    在这里插入图片描述

  • 将刚制作的 mytomcat 镜像标记:

    docker tag mytomcat 1260168395/mytomcat:1.0
    
(3)发布镜像到docker hub:
  • 命令:docker push [OPTIONS] NAME[:TAG]

  • 将 mytomcat 镜像发送到 docker hub 上:

    docker push 1260168395/mytomcat:1.0
    
(4)登出 docker logout
  • 命令:docker logout [SERVER]

8. 发布镜像到阿里云容器服务

  1. 登录阿里云(https://www.aliyun.com/),找到容器与镜像服务(找不到的可以参考 2.2 配置阿里云镜像加速

  2. 创建命名空间
    在这里插入图片描述

  3. 创建镜像仓库

    1. 点击创建镜像
      在这里插入图片描述
    2. 填写仓库信息
    3. 选择代码源,这里使用的是本地仓库这个代码源:
      在这里插入图片描述
  4. 发布镜像
    点击刚创建好的镜像仓库,查看镜像仓库的详细信息,仓库中会如何提交镜像到这个仓库的说明与命令,自行参考自己的即可。

    在这里插入图片描述

七、Docker Compose

Docker Compose 官方文档:https://docs.docker.com/compose/

1. 简介

  • 前面我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker builddocker run 等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知
  • 使用 Docker Compose 可以轻松、高效的管理多个容器,它是一个用于定义和运行多容器 Docker 的应用程序工具

使用 Compose 基本上是一个三步过程:

  1. 首先使用 Dockerfile 定义自己的环境,以便可以在任何地方复制。

  2. docker-compose.yml 文件中定义组成应用程序的服务,以便它们可以在隔离的环境中一起运行。

  3. 执行 docker-compose up 命令,启动并运行整个应用程序。

一个 docker-compose.yml 看起来像这样:

version: "3.8"
services:
  web:
    build: .	# 使用当前目录中的 Dockerfile 构建 web 镜像
    ports:		# 暴露端口
      - "5000:5000"		
    volumes:	# 卷挂载
      - .:/code
      - logvolume01:/var/log
    links:		# 与下面定义的 redis 服务(容器)连接
      - redis
  redis:
    image: redis	# 使用 redis 镜像
volumes:
  logvolume01: {}	# 定义卷名

2. 安装

官方文档,这里有各个系统的安装方法:https://docs.docker.com/compose/install/

Linux(Centos7)安装

  1. 下载
    可以选择从官网下载或者是 DaoCloud 下载

    # 这里是1.27.4版本的,其它版本要替换链接中的1.27.4
    # 这是官网的地址
    sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    
    # 这是 DaoCloud 地址
    curl -L https://get.daocloud.io/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    
  2. 将可执行权限应用于二进制文件

    sudo chmod +x /usr/local/bin/docker-compose
    
  3. 执行 docker-compose version 查看是否安装成功

3. 快速开始

这是来自官网的一个入门小例子 :https://docs.docker.com/compose/gettingstarted/

我这里对官网的例子稍做修改,使例子更加简洁

  1. 为项目创建目录:

    mkdir composetest
    cd composetest
    
  2. 在刚创建的项目目录中创建一个名为 app.py 的文件,并粘贴如下代码:

    import time
    
    import redis
    from flask import Flask
    
    app = Flask(__name__)
    # 注意这里的小细节,访问 redis 时,host 并不是ip地址,而是域名(服务名) redis
    cache = redis.Redis(host='redis', port=6379)
    
    def get_hit_count():
        retries = 5
        while True:
            try:
            	# 每访问一次,通过 redis 自增 1
                return cache.incr('hits')
            except redis.exceptions.ConnectionError as exc:
                if retries == 0:
                    raise exc
                retries -= 1
                time.sleep(0.5)
    
    @app.route('/')
    def hello():
        count = get_hit_count()
        return 'Hello World! I have been seen {} times.\n'.format(count)
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", debug=True)
    
  3. 在项目目录中创建另一个名为 requirements.txt 的文件,并粘贴如下代码:

    flask
    redis
    
  4. 在项目目录中,创建一个名为 Dockerfile 的文件,并粘贴以下内容:

    FROM python:3.7-alpine
    ADD . /code
    WORKDIR /code
    
    RUN pip install -r requirements.txt
    CMD ["python", "app.py"]
    
  5. 在项目目录中创建一个名为 docker-compose.yml 的文件,然后粘贴以下内容:

    version: "3.8"
    services:
      web:
        build: .
        ports:
          - "5000:5000"
      redis:
        image: "redis:alpine"
    
  6. 在项目目录中,通过 docker-compose up 运行来启动应用程序。

  7. 在浏览器中输入 http://localhost:5000 以查看该应用程序正在运行。
    在这里插入图片描述

  8. 可以看到,启动了两个服务:

    默认的容器名:文件名_服务名_副本数量
    在这里插入图片描述

  9. 查看网络
    Docker Compose 会自动生成一个网络,启动的服务都在这个网络中,所以服务之间可以通过域名(服务名)访问
    在这里插入图片描述

  10. 其它命令

    1. 后台运行

      docker-compose up -d
      
    2. 查看当前正在运行的服务

      docker-compose ps
      
    3. 如果是后台运行的话,使用下面的命令停止

      注意:要在启动时的那个目录下执行

      docker-compose stop
      

    在这里插入图片描述

4. yaml配置文件

官方文档:https://docs.docker.com/compose/compose-file/
菜鸟教程:https://www.runoob.com/docker/docker-compose.html

version:版本

指定本 yml 依从的 compose 哪个版本制定的。向下兼容,最新的是 3.8

services:多个容器集合

build:指定Dockerfile

指定 Dockerfile 的上下文路径或者是一个对象,该对象可以指定 Dockerfile 的参数:

version: "3.7"
services:
  webapp:
    build: ./dir
    
  webapp2:
  	build:
      context: ./dir 	# 上下文路径
      dockerfile: Dockerfile-alternate 	# 指定构建镜像的 Dockerfile 文件名
      args:		# 添加构建参数,这是只能在构建过程中访问的环境变量
        buildno: 1
      labels:	# 设置构建镜像的标签
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod		# 多层构建,可以指定构建哪一层

command:覆盖容器启动后默认执行的命令

command: ["bundle", "exec", "thin", "-p", "3000"]

container_name:自定义生成的容器名称

自定义生成的容器名称,而不是生成的默认名称

container_name: my-web-container

depends_on:设置依赖关系

version: "3.8"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

注意:web 服务不会等待 redis db 完全启动 之后才启动。

docker-compose up :以依赖性顺序启动服务。示例中,先启动 db 和 redis ,才会启动 web。
docker-compose up SERVICE :自动包含 SERVICE 的依赖项。示例中,docker-compose up web 还将创建并启动 db 和 redis。
docker-compose stop :按依赖关系顺序停止服务。示例中,web 在 db 和 redis 之前停止。

dns:配置 dns 服务器

配置 dns 服务器,可以是一个值或列表

dns: 8.8.8.8

dns:
    - 8.8.8.8
    - 9.9.9.9

dns_search:配置 DNS 搜索域

配置 DNS 搜索域,可以是一个值或列表

dns_search: example.com

dns_search:
    - dc1.example.com
    - dc2.example.com

env_file:从文件中获取环境变量

从文件中获取环境变量,可以指定一个文件路径或路径列表,其优先级低于 environment 指定的环境变量。可以是单个值或列表的多个值。

env_file: .env

env_file:
    - ./common.env

environment:环境变量配置

添加环境变量配置,可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。

environment:
    RACK_ENV: development
    SHOW: 'ture'

entrypoint:启动容器后执行的命令

会覆盖容器默认的 entrypoint 或者 dockerFile 中的 CMD 命令。

entrypoint: /code/entrypoint.sh

也可以是以下格式:

entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit

expose:暴露端口

暴露端口,只将端口暴露给连接的服务,而不暴露给主机,仅可以指定内部端口为参数

expose:
    - "3000"
    - "8000"

extra_hosts:添加主机名映射

添加主机名映射,类似 docker client --add-host。

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:

162.242.195.82  somehost
50.31.209.229   otherhost

image:指定服务所使用的镜像

image: java
image: a4bc65fd # 镜像id

links:链接到另一个服务中的容器

链接到另一个服务中的容器。指定服务名称和链接别名(“SERVICE:ALIAS”),或者仅指定服务名称。

可以使用与别名相同的主机名访问链接服务的容器,如果未指定别名,则可以使用服务名。

version: "3"
services:
  web:
    links:
      - "db"
      - "db:database"
  db:
    image: postgres

logging:服务的日志记录配置

driver:指定服务容器的日志记录驱动程序,默认值为json-file。有以下三个选项

driver: "json-file"
driver: "syslog"
driver: "none"
  • 仅在 json-file 驱动程序下,可以使用以下参数,限制日志得数量和大小。

    logging:
      driver: json-file
      options:
        max-size: "200k" # 单个文件大小为200k
        max-file: "10" # 最多10个文件
    

    当达到文件限制上限,会自动删除旧得文件。

  • syslog 驱动程序下,可以使用 syslog-address 指定日志接收地址。

    logging:
      driver: syslog
      options:
        syslog-address: "tcp://192.168.0.42:123"
    

network_mode:设置网络模式

使用与 docker client--network 参数相同的值,以及特殊形式 service:[service name]

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks:配置容器连接的网络

配置容器连接的网络,引用顶级 networks 下的条目 。

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:  	# 同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2

ports:对外暴露的端口定义,和 expose 对应

ports:   # 暴露端口信息  - "宿主机端口:容器暴露端口"
- "5000:5000"
- "8763:8763"

volumes:卷挂载路径

将主机的数据卷或着文件挂载到容器里。使用方法:主机路径或卷名 : 容器路径(在顶级的 volumes 中定义卷名)

version: "3.8"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "dbdata:/var/lib/postgresql/data"
volumes:
  dbdata:

restart: always:设置容器自启动

version: "3.8"
services:
    mysql:
        image: mysql:5.7
        volumes:
            - "/mydata/mysql/log:/var/log/mysql"
            - "/mydata/mysql/data:/var/lib/mysql"
            - "/mydata/mysql/conf:/etc/mysql"
        ports:
            - "3306:3306"
        environment:
            MYSQL_ROOT_PASSWORD: "root"
        restart: always
    redis:
        image: redis
        volumes:
            - "/mydata/redis/data:/data"
            - "/mydata/redis/conf/redis.conf:/etc/redis/redis.conf"
        ports:
            - "6379:6379"
        entrypoint: ["redis-server", "/etc/redis/redis.conf"]
        restart: always

5. 常用命令

官方文档:https://docs.docker.com/compose/reference/build/

命令说明举例
ps列出所有运行容器docker-compose ps
logs查看服务日志输出docker-compose logs
port打印绑定的公共端口,下面命令可以输出 eureka 服务 8761 端口所绑定的公共端口docker-compose port eureka 8761
build构建或者重新构建服务docker-compose build
start启动指定服务已存在的容器docker-compose start eureka
stop停止已运行的服务的容器docker-compose stop eureka
rm删除指定服务的容器docker-compose rm eureka
up构建、启动容器docker-compose up
开启容器之前先构建镜像:docker-compose up --build
后台运行:docker-compose up -d
kill通过发送 SIGKILL 信号来停止指定服务的容器docker-compose kill eureka
pull下载服务镜像
scale设置指定服务运行容器的个数,以 service=num 形式指定docker-compose scale user=3 movie=3
run在一个服务上执行一个命令docker-compose run web bash

八、可视化

1. portainer

文档:https://www.portainer.io/documentation/

跟着文档走就可以了,以下是对我的操作做个笔记

  1. 安装
    docker volume create portainer_data
    docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
    
  2. 浏览器访问 9000 端口即可。

九、示例

1. 部署Mysql

  1. 服务器可以连接外网,直接从仓库 pull 镜像

    docker pull mysql:5.7
    
  2. 服务器不可以连接外网,则先从一个有网络的电脑下载 mysql 镜像,然后再将镜像保存到本地,再把镜像发送到没有网的服务器,最后通过 docker 加载镜像即可:

    1. 保存镜像到本地文件

      docker save -o mysql5.7 mysql:5.7
      
    2. 把镜像拷贝到无网络的电脑,然后通过docker加载镜像即可。

      sudo docker load -i mysql5.7
      
  3. 启动 mysql 容器

    docker run -dit -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 --name="mysql01" mysql:5.7
    

2. 部署Nginx

  1. 搜索镜像,可以使用 docker search 命令去搜索,我更推荐去 Docker Hub(https://hub.docker.com/) 上去搜索,第一次进入 Docker Hub 需要注册一下,注册登录之后直接搜索Nginx:
    在这里插入图片描述
    点进去之后,会有版本信息,镜像的使用(配置)等一些信息。

  2. 拉取镜像,若没有网络,则处理方式与 Mysql 镜像相同

    docker pull nginx
    
  3. 启动临时容器,获取 nginx 的配置文件

# 先随便启动一个 Nginx 容器
docker run --name nginx-tmp -d -p 80:80 nginx

# 将nginx容器中的nginx目录复制到本机的/mydata/nginx/conf目录
docker container cp nginx:/etc/nginx /mydata/nginx/conf

# 复制的是nginx目录,将该目录的所有文件移动到 conf 目录
mv /mydata/nginx/conf/nginx/* /mydata/nginx/conf/

# 删除多余的 /mydata/nginx/conf/nginx目录
rm -rf /mydata/nginx/conf/nginx

# 停止运行 nginx 容器
docker stop nginx-tmp

# 删除 nginx 容器
docker rm nginx-tmp
  1. 启动 nginx 容器
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf/:/etc/nginx \
-d nginx:1.10
--restart=always
  1. 测试 nginx
echo '<h1><a target="_blank" href="https://github.com/zsy0216/guli-mall">nginx配置成功</a></h1>' \
>/mydata/nginx/html/index.html

浏览器访问 ip:80,看到上面配置的 index.html 页面,则 nginx 启动成功

3. 部署Tomcat

  1. 同样,先上 Docker Hub 上搜索 Tomcat,然后找到对应的版本进行 pull

    docker pull tomcat:9.0
    
  2. 启动一个 Tomcat 容器

    docker run -d -p 8080:8080 --name tomcat01 tomcat
    
  3. Tomcat 容器的一些配置

    1. Tomcat 容器中,Tomcat 的位置在/usr/local/tomcat,其中,webapps文件夹中内容为空,原本的内容全在 webapps.dist 文件夹下。
    2. 配置文件位于 /usr/local/tomcat/conf/
  4. webapps 文件夹下有内容后,通过浏览器访问来查看 Tomcat 是否配置成功

4. docker-compose使用案例

注意:nginx 要先启一个临时的容器,获取配置文件,放到要挂载的目录,再启动正式的 nginx

version: "3.8"
services:
        mysql:
                image: mysql:5.7
                volumes:
                        - "/mydata/mysql/log:/var/log/mysql"
                        - "/mydata/mysql/data:/var/lib/mysql"
                        - "/mydata/mysql/conf:/etc/mysql"
                ports:
                        - "3306:3306"
                environment:
                        MYSQL_ROOT_PASSWORD: "root"
                restart: always
        redis:
                image: redis
                volumes:
                        - "/mydata/redis/data:/data"
                        - "/mydata/redis/conf/redis.conf:/etc/redis/redis.conf"
                ports:
                        - "6379:6379"
                entrypoint: ["redis-server", "/etc/redis/redis.conf"]
                restart: always
        nacos:
                image: nacos/nacos-server:2.0.1
                ports:
                        - "8848:8848"
                environment:
                        MODE: "standalone"
                restart: always
        nginx:
                image: nginx:1.18.0
                ports:
                        - "80:80"
                volumes:
                        - "/mydata/nginx/conf:/etc/nginx"
                        - "/mydata/nginx/html:/usr/share/nginx/html"
                        - "/mydata/nginx/logs:/var/log/nginx"
                restart: always
        elasticsearch:
                image: elasticsearch:7.4.2
                ports:
                        - "9200:9200"
                        - "9300:9300"
                environment:
                        discovery.type: "single-node"
                        ES_JAVA_OPTS: "-Xms64m -Xmx512m"
                volumes:
                        - "/mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml"
                        - "/mydata/elasticsearch/data:/usr/share/elasticsearch/data"
                        - "/mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins"
                restart: always
        kibana:
                image: kibana:7.4.2
                ports:
                        - "5601:5601"
                environment:
                        ELASTICSEARCH_HOSTS: "http://10.211.55.12:9200"
                restart: always
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值