Docker 容器技术初探

Docker 容器技术初探

一、 docker 简介

1. 容器简介

① 容器是什么
  • 容器是一种轻量级、可移植、自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行。开发人员在自己笔记本上创建并测试好的容器,无需任何修改就能够在生产系统的虚拟机、物理服务器或公有云主机上运行。

容器由两部分组成:

  • 应用程序
  • 依赖(应用程序需要的库或其他软件)

② 容器和虚拟机的区别
  • 虚拟机需要模拟整个操作系统。而容器运行在 Host 操作系统的用户空间,与操作系统的其他进程隔离,所有的容器共享同一个 Host OS,这使得容器在体积上比虚拟机小很多。
  • 启动容器不需要启动整个操作系统,所以容器部署和启动速度更快,开销更小,也更容易迁移。

③ 为什么使用容器

容器使软件具备了超强的可移植能力。

  • 现今的软件应用往往依赖多种服务,这些服务也有自己的依赖,同时应用可能需要被部署或迁移到不同的环境,需要一种通用的解决办法使得服务在不同的环境下都能顺利运行。

容器有着可重复性和环境隔离。

  • 开发人员只需为应用创建一次运行环境,然后打包成容器便可在其他机器上运行。另外,容器环境与所在的 Host 环境是隔离的。

配置好标准的环境,服务器就可以运行任何容器

  • 运维人员的工作变得更高效,一致和可重复。容器消除了开发、测试、生产环境的不一致性。

④ docker 和容器的关系
  • Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux 或 Windows 机器上,也可以实现虚拟化。
  • 从 docker 的 logo 我们可以看出它采用了集装箱原理。在没有使用集装箱的情况下,我们需要考虑不同形状、尺寸的货物怎么安放,货物与货物之间是否能堆叠,这无疑是很繁琐的事情。
  • 有了集装箱(容器),我们就能将不同的货物放入集装箱之内这样就能以同样的方式来存放货物,实现了标准化。

在这里插入图片描述

2. 为什么需要 docker?

在这里插入图片描述

  • 灵活:即使是最复杂的应用也可以容器化。
  • 轻量:容器是进程,能利用并共享主机操作系统内核。
  • 替换:可以即时部署更新和升级容器。
  • 便携:可以在本地构建,部署到云并在任何地方运行。
  • 扩展:您可以增加并自动分发容器副本。
  • 组合: 您可以自由地组合(stack)服务

3. docker 核心概念

  • 镜像(image) – 类比执行程序,一个可执行的包,包含运行应用程序所需的一切——代码、运行时、库、环境变量和配置文件。
  • 容器(Container) – 类比进程,镜像的运行时实例——镜像在执行时在内存中成为什么(即带有状态的镜像,或用户进程)
  • 仓库(Registry) – 类比 repository,存放不同版本镜像的地方
  • 主机(Host / Node) – 运行容器的服务器
  • 服务(Service) – 一个镜像之上运行的一组可伸缩的容器集合,运行在一个容器集群中提供同一功能服务
  • 栈(Stack) / 命名空间(Namaspace) / 应用(Application) – 被编排的、可伸缩的一组相互依赖的服务,构成的一个应用

4. docker 引擎与工作原理

在这里插入图片描述

二、 docker 环境准备

1. 系统环境

  • 硬件信息:virtual box 虚拟机(内存5G、磁盘20G)
  • 操作系统:Centos 7
  • 编程语言:go version go1.13.1 linux/amd64
  • 如果你不是 root 用户,请将用户加入 docker 用户组,具体做法可参考笔者的另一篇博客 Docker 安装使用过程的坑

2. docker 安装

  • 如果之前安装过 docker,请先删除
sudo yum remove docker docker-common docker-selinux docker-engine

在这里插入图片描述

  • 安装依赖,期间可能报错 failure: repodata/repomd.xml from mirrors.aliyun.com_docker-ce_linux_centos_docker-ce.pro,具体做法可参考笔者的另一篇博客 Docker 安装使用过程的坑
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

在这里插入图片描述

  • 下载 repo 文件
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo

在这里插入图片描述

  • 把软件仓库地址替换为清华源
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
  • 安装
sudo yum makecache fast
sudo yum install docker-ce

在这里插入图片描述
在这里插入图片描述

  • 检查 docker 安装,输出 Docker 版本号
docker version

在这里插入图片描述

三、docker 的使用

1. 镜像学习

镜像是 Docker 容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。可以运行镜像检查是否成功安装

① hello-world 镜像
  • hello-world 镜像是 Docker 官方提供的一个镜像,我们执行如下操作运行镜像 hello-world
docker run hello-world
  • 首次运行会出现找不到 image 'hello-world:latest’ 的情况,不过 docker 会自动从Docker Hub 上获取到最新的 Hello World 镜像,并下载到本地

在这里插入图片描述

  • 从上述运行结果的输出,我们可以了解到镜像的运行里面涉及到了容器客户端与容器服务器的交互,以及容器和镜像之间的关系。

② ubuntu bash 镜像
docker run -it ubuntu bash
  • -it 参数,通过终端与进程(容器)交互,stdin,stdout,stderr定向到 TTY
  • 这里可能需要更换为国内镜像(因为默认是从 Docker Hub 拉取镜像,而国内从 Docker Hub 拉取镜像有时会遇到困难),具体做法可参考笔者的另一篇博客 Docker 安装使用过程的坑
  • 输出结果如下
    在这里插入图片描述
③ httpd 镜像
docker run -d -p 80:80 httpd
  • 下载 httpd 镜像。启动 httpd 容器,并将容器的 80 端口映射到 host 的 80 端口。
    在这里插入图片描述
  • 打开浏览器输入 localhost ,出现如下界面,表明可以访问容器的 http 服务,容器运行成功
    在这里插入图片描述

④ 镜像的分层结构

在这里插入图片描述

  • Docker 支持通过扩展现有镜像,创建新的镜像。新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。这种做法的最大一个好处就是:共享资源。例如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。
    在这里插入图片描述
  • 但是,虽然低层的镜像被共享了,不同容器对其进行修改却不会造成混乱,所有的修改会被限制在单个容器内。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。

添加文件:在容器中创建文件时,新文件被添加到容器层中。
读取文件:在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
修改文件:在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
删除文件:在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。

  • 只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
  • 容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。

2. docker 常用命令

  • docker run/build
  • build 构建镜像,run 运行镜像创建容器
    在这里插入图片描述
  • docker images
  • 查看本地镜像库内容

REPOSITORY:镜像所属仓库名称
TAG:镜像标签。默认是latest,表示最新
IMAGE ID:镜像ID,表示镜像唯一标标识
CREATED:镜像创建时间
SIZE:镜像大小

在这里插入图片描述

  • docker ps [-a]
  • 查看正在运行的容器,加上 -a 查看所有容器

CONTAINER_ID:表示容器ID
IMAGE:表示镜像名称
IMAGE:表示镜像名称
CREATED:表示容器创建时间
STATUS:表示容器运行状态。UP表示运行中,Exited表示已停止
PORTS:表示容器对外的端口号
NAMES:表示容器名称,该名称默认由Docker自动生成,也可使用docker run命令的–name选项自定指定

在这里插入图片描述

  • docker stop/kill
  • 安全停止/直接杀死正在运行的容器
  • docker --help
  • 获得帮助

– 基本选项
– 管理命令(至少掌握 container, image, network, volume)
– 常用命令
• 例如: docker images 等价于 docker image ls
• 例如: docker ps 等价于 docker container ls

在这里插入图片描述

  • docker network
  • 网络相关命令
    在这里插入图片描述
  • 继续运行原容器并进入
~]# docker restart frosty_goodall
~]# docker ps
~]# docker attach frosty_goodall
root@e2442527555f:/# exit

3. MySQL与容器化

① 下载拉取 MySQL 镜像
  • 执行该命令后,Docker 会从 Docker Hub 中的 mysql 仓库下载最新版镜像

在这里插入图片描述

② 构建 docker 镜像
1)Dockerfile

构建镜像有两种方式

  • 使用 docker commit 命令
  • 或通过 Dockerfile 构建文件,是一般使用的方式

Dockerfile 是一个文本文件,记录了镜像构建的所有步骤。

  • 具体操作主要是拉取源,声明工作目录,导入项目,执行项目的运行步骤

2)Dockerfile 常用指令
指令作用
FROM指定 base 镜像
COPY将文件从 build context 复制到镜像
ENV设置环境变量,环境变量可被后面的指令使用
EXPOSE指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来
VOLUME将文件或目录声明为 volume
RUN在容器中运行指定的命令
CMD容器启动时运行指定的命令。Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。CMD 可以被 docker run 之后的参数替换
ENTRYPOINT设置容器启动时运行的命令

3)编辑 Dockerfile
  • 以下是一个 Dockerfile 的实例
  • 从终端进入 dockerfile
mkdir mydock && cd mydock
vim dockerfile
  • 在文件中输入以下内容
  • 在该文件中,我们指明镜像基于 ubuntu:latest 镜像,镜像启动后运行 top -b -c 命令。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

4)构建和运行镜像
  • 构建镜像
    在这里插入图片描述
  • 运行镜像
  • -it 表示可交互式的 TTY 界面,-rm 表示容器运行完毕后删除此容器
    在这里插入图片描述

③ 使用 MySQL 镜像
  • 启动服务器
  • 通过 -p 进行端口映射
  • 通过 -e 设置容器的环境变量参数
    在这里插入图片描述
  • 启动 MySQL 客户端
    在这里插入图片描述

-it 等价于 -i -t ,表示使用当前 stdin 和 stdout 作为该进程的 io
–rm , 当该进程结束时,自动清理该容器的文件系统空间
–net host,表示容器使用当前主机的网络环境

  • 数据库文件位置
  • Dockerfile 的 VOLUME /var/lib/mysql 的含义

– 每次启动 mysql 容器, docker 创建一个文件卷挂载在容器内/var/lib/mysql位置
– 这个卷在主机(host)的 /var/lib/docker/volumes/ 目录下

在这里插入图片描述

  • 创建卷并挂载
  • 将自己定义的数据卷挂载在 /var/lib/mysql
    在这里插入图片描述
  • 启动客户端连接服务器
  • 使用 --link 使得 myclient 和 hellomysql 容器链接在一起
  • 客户端容器内可以使用 mysql 这个别名访问服务器
  • 启动 bash 命令后,输入 env 查看环境变量
  • 启动 mysql 客户端链接到服务器
    在这里插入图片描述
  • 挂载现有数据库
  • 官网案例:
docker run -v "$PWD/data":/var/lib/mysql --user 1000:1000 --name
some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
  • 修改容器配置
  • 官网案例:
docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

④ Docker compose 与多容器应用自动化部署
  • Docker Compose 是一个多容器应用自动化部署工具,可大大提高容器部署效率,其通过解析 docker-compose.yml 文件中的配置,实现容器的自动化部署。
  • 下载 docker-compose(容器编排的原型)
  • 有可能会显示 ”没有可用软件包“,这时需要离线下载安装,具体做法可参考笔者的另一篇博客 Docker 安装使用过程的坑
yum install docker-compose
  • 授权和查看版本
    在这里插入图片描述
  • 创建目录并编写 stack.yml
    在这里插入图片描述
  • 我们声明了两个 services ,分别是 dbadminer
  • db 中,我们指明了所使用的镜像、密码配置和重启策略;
  • adminer 中,我们指明了所使用的镜像、重启策略和端口映射。
version: '3.1'
services:
 db:
  image: mysql:5.7
  command: --default-authentication-plugin=mysql_native_password
  restart: always
  environment:
   MYSQL_ROOT_PASSWORD: 19970805
 adminer:
  image: adminer
  restart: always
  ports:
   - 8080:8080
  • 通过执行 docker-compose up -d 命令,我们即可启动 db 和 adminer 两个容器
docker-compose -f stack.yml up -d

在这里插入图片描述

  • 我们可在浏览器中访问 :8080 端口,进入 Adminer 管理页面
    在这里插入图片描述
  • 输入 db 用户名 root 和密码后,即可进入到数据库管理页面
    在这里插入图片描述
  • 可以执行以下命令来终止上述两个容器的运行
docker-compose down

4. docker 网络

  • 管理容器网络
    在这里插入图片描述

  • 自定义容器网络,备制支持 ifconfigping 命令的 ubuntu 容器
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 启动另一个命令窗口,由容器制作镜像
    在这里插入图片描述

  • 创建自定义网络
    在这里插入图片描述

  • 在另外两个窗口分别创建 u1,u2 容器网络

docker run --name u1 -it -p 8080:80 --net mynet --rm ubuntu:net bash
docker run --name u2 --net mynet -it --rm ubuntu:net bash

在这里插入图片描述

  • 执行以下命令
[root@localhost beilineili]# docker inspect u1
[
    {
        "Id": "243cd28b9df8cb89d41bc90fab534d0d5f9839e1cfb6dea7541b443b9d6fbf3e",
        "Created": "2020-12-26T07:35:39.72179261Z",
        "Path": "bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 10227,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-12-26T07:35:40.247350341Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:4229b24e447b5187e2db1ab328caf88b7c7e15e7dd0f31baa0f74a6116366471",
        "ResolvConfPath": "/var/lib/docker/containers/243cd28b9df8cb89d41bc90fab534d0d5f9839e1cfb6dea7541b443b9d6fbf3e/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/243cd28b9df8cb89d41bc90fab534d0d5f9839e1cfb6dea7541b443b9d6fbf3e/hostname",
        "HostsPath": "/var/lib/docker/containers/243cd28b9df8cb89d41bc90fab534d0d5f9839e1cfb6dea7541b443b9d6fbf3e/hosts",
        "LogPath": "/var/lib/docker/containers/243cd28b9df8cb89d41bc90fab534d0d5f9839e1cfb6dea7541b443b9d6fbf3e/243cd28b9df8cb89d41bc90fab534d0d5f9839e1cfb6dea7541b443b9d6fbf3e-json.log",
        "Name": "/u1",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "mynet",
            "PortBindings": {
                "80/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "8082"
                    }
                ]
            },
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": true,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "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/ff3ce156d5aca31ec2fe109f12024633a7c9a1e9ecc40b11c82bbc9388b6c946-init/diff:/var/lib/docker/overlay2/9fc69e17121896d1357445fa9e01f2f9542f5d16505b384d39d3f7f2ac4c04cf/diff:/var/lib/docker/overlay2/695290cd3d06c60f2631255a67cbd585a52e2b2080ef481c2483f3b174adb4f2/diff:/var/lib/docker/overlay2/72e5de74f595ffbbd0c8ea8905f176bf1104d3483e1d33a637b76953e2607b67/diff:/var/lib/docker/overlay2/da0f84bbb5974a5eb0fd4b77d65516cbc7e1df4c65a80a0c3de81efe7910153a/diff",
                "MergedDir": "/var/lib/docker/overlay2/ff3ce156d5aca31ec2fe109f12024633a7c9a1e9ecc40b11c82bbc9388b6c946/merged",
                "UpperDir": "/var/lib/docker/overlay2/ff3ce156d5aca31ec2fe109f12024633a7c9a1e9ecc40b11c82bbc9388b6c946/diff",
                "WorkDir": "/var/lib/docker/overlay2/ff3ce156d5aca31ec2fe109f12024633a7c9a1e9ecc40b11c82bbc9388b6c946/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "243cd28b9df8",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "bash"
            ],
            "Image": "ubuntu:net",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "89b67126e91ef207bfe5f812edca9a2addaad2ce76b915397bfd49970aebff05",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "80/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "8082"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/89b67126e91e",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "",
            "Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "MacAddress": "",
            "Networks": {
                "mynet": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "243cd28b9df8"
                    ],
                    "NetworkID": "e2be683e596b3d5fa651af6b9cccd79dc386aeb5d479b285156b1e8a515ee432",
                    "EndpointID": "2fcb9b77d2b0710b18d3e1f0d3e514e1bd5f9b9a6f57ed242a9af219ac57b3a0",
                    "Gateway": "172.19.0.1",
                    "IPAddress": "172.19.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:13:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
[root@localhost beilineili]# docker network connect bridge u1
[root@localhost beilineili]# docker network disconnect mynet u1

5. docker 仓库 (Registry)

以阿里云容器镜像服务的教程如下:

  • 访问 阿里云
  • 注册一个账号
  • 选择“容器镜像服务”
① 常用仓库操作
  • 上传 hello-world 镜像
• 登陆 docker login --username= registry.cn-shenzhen.aliyuncs.com 

• 标签 docker tag hello-world registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:helloworld 

• 上传 docker push registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:hello-world 

• 下载 docker push registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:hello-world 

• 标签 docker tag registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:hello-world helloworld 

• 删除 docker rmi registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:hello-world 

• 运行 docker run --rm hello-world 

• 退出 docker logout registry.cn-shenzhen.aliyuncs.com 
  • 检查 docker 的状态
docker info … … 

docker info --format {{.ServerVersion}} 
  • 查看容器内进程
Docker top 

Docker stats 
  • 容器详细信息
docker inspect … … 

docker inspect -f '{{.NetworkSettings.IPAddress}}' 084f46eddf33 172.17.0.2 
  • 容器的日志 – 容器应用的 stdout 与 stderr 输出
  • 容器日志查看
~]# docker logs 084f46eddf33
root@084f46eddf33:/# ll
total 12
drwxr-xr-x. 1 root root 43 Dec 13 13:46 ./
drwxr-xr-x. 1 root root 43 Dec 13 13:46 ../
-rwxr-xr-x. 1 root root 0 Dec 13 13:46 .dockerenv*
drwxr-xr-x. 2 root root 4096 Dec 12 03:44 bin/
…
~]# docker logs --tail 2 084f46eddf33
drwxr-xr-x. 10 root root 97 Dec 10 08:42 usr/
drwxr-xr-x. 11 root root 4096 Dec 10 08:42 var/
  • 日志的重要性!-- 调试、分析

四、参考文章

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值