添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

本文是 Docker 的简易使用指南,包含方方面面的知识,争取通过本文能够对 Docker 有个初步的了解。

Docker安装

这部分以 CentOS Ubuntu 为例,根据 Docker 官网给出的 安装教程 进行整理和总结。

CentOS

确定你是CentOS7及以上版本
1cat /etc/redhat-release # centos
卸载旧版本
1sudo yum remove docker \
2                docker-client \
3                docker-client-latest \
4                docker-common \
5                docker-latest \
6                docker-latest-logrotate \
7                docker-logrotate \
8                docker-engine
yum安装gcc相关
1# 前提:CentOS能上外网
2sudo yum -y install gcc
3sudo yum -y install gcc-c++
安装需要的软件包
1sudo yum install -y yum-utils
设置stable镜像仓库

因为防火墙的原因,中国大陆地区需要设置可靠的镜像仓库,以阿里云为例。

1sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新yum软件包索引
1sudo yum makecache fast
安装Docker CE
1sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
启动Docker
1sudo systemctl start docker
1sudo docker version
2sudo docker run hello-world
卸载Docker引擎
  • 卸载 Docker EngineCLIContainerdDocker Compose 软件包:
  • 1sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
    
  • 主机上的映像、容器、卷或自定义配置文件不会自动删除。要删除所有映像、容器和卷:
  • 1sudo rm -rf /var/lib/docker
    2sudo rm -rf /var/lib/containerd
    

    最后,必须手动删除编辑过的配置文件。

    Ubuntu

    确定是Ubuntu20.04及以上版本
    1cat /etc/os-release # ubuntu
    
    卸载旧版本
    1for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
    
    设置apt仓库

    第一次安装docker,需要先设置apt仓库。

     1# Add Docker's official GPG key:
     2sudo apt-get update
     3sudo apt-get install ca-certificates curl gnupg
     4sudo install -m 0755 -d /etc/apt/keyrings
     5curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
     6sudo chmod a+r /etc/apt/keyrings/docker.gpg
     8# Add the repository to Apt sources:
     9echo \
    10  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
    11  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
    12  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    13sudo apt-get update
    
    安装最新版
    1sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
    1sudo docker version
    2sudo docker run hello-world
    
  • 卸载 Docker EngineCLIContainerdDocker Compose 软件包:
  • 1sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
    
  • 主机上的映像、容器、卷或自定义配置文件不会自动删除。要删除所有映像、容器和卷:
  • 1sudo rm -rf /var/lib/docker
    2sudo rm -rf /var/lib/containerd
    

    最后,必须手动删除编辑过的配置文件。

    Docker免sudo权限

    安装完 Docker,每次必须用 sudo 权限操作,比较麻烦。将 Docker 加入 sudo 用户组,即可默认 sudo 权限运行,而不用 sudo。具体步骤如下:

  • 添加 docker group
  • 1sudo groupadd docker
    
  • 将当前用户添加到 docker
  • 1sudo gpasswd -a ${USER} docker
    
  • 重启 docker 服务
  • 1systemctl restart docker
    
  • 刷新 docker 组成员
  • 1newgrp - docker
    

    这样,再次使用 docker 命令,无需添加 sudo

    阿里云镜像加速

    是什么 https://promotion.aliyun.com/ntms/act/kubernetes.html

    注册一个属于自己的阿里云账户(可复用支付宝账号)

    获得加速器地址连接

    登陆阿里云开发者平台

    推荐安装 1.10.0 以上版本的 Docker 客户端,参考文档docker-ce

    配置镜像加速器

    针对 Docker 客户端版本大于 1.10.0 的用户,可以通过修改 daemon 配置文件 /etc/docker/daemon.json 来使用加速器。

    1sudo mkdir -p /etc/docker
    2sudo tee /etc/docker/daemon.json <<-'EOF'
    4  "registry-mirrors": ["https://wivds1wh.mirror.aliyuncs.com"]
    6EOF
    7sudo systemctl daemon-reload
    

    重启服务器

    1sudo systemctl restart docker
    

    Docker常用命令

    帮助启动类命令

     1# 启动docker
     2systemctl start docker
     4# 停止docker
     5systemctl stop docker
     7# 重启docker
     8systemctl restart docker
    10# 查看docker状态
    11systemctl status docker
    13# 开机启动
    14systemctl enable docker
    16# 查看docker概要信息
    17docker info
    19# 查看docker总体帮助文档
    20docker --help
    22# 查看docker命令帮助文档
    23docker 具体命令 --help
    

    docker images [OPTIONS] [REPOSITORY[:TAG]]

    1、列出本地主机上的镜像

    1$ docker images
    2REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
    3ubuntu        latest    27941809078c   2 weeks ago    77.8MB
    4hello-world   latest    feb5d9fea6a5   9 months ago   13.3kB
    

    各个选项说明

    注:同一仓库源可以有多个 TAG 版本,代表这个仓库源的不同版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果你不指定一个镜像的版本标签,例如你只使用 ubuntuDocker 将默认使用 ubuntu:latest 镜像。

    2、OPTIONS 说明

    -a:列出本地所有的镜像(含历史影像层)

    -q:只显示镜像 ID

    docker search [OPTIONS] TERM

    https://hub.docker.com

    1docker search [OPTIONS] 镜像名字
    
    1$ docker search redis
    2NAME  DESCRIPTION        							  STARS     OFFICIAL   AUTOMATED
    3redis Redis is an open source key-value store that…   11050     [OK]       
    4...
    

    OPTIONS说明

    --limit:只列出N个镜像,默认25

    1docker search --limit 5 redis
    

    docker pull [OPTIONS] NAME[:TAG|@DIGEST]

    下载镜像命令

    1docker pull 镜像名字[:TAG]
    

    注:没有 TAG 就是最新版,等价于 docker pull 镜像名字:latest

    docker system df

    查看镜像/容器/数据卷所占的空间

    1$ docker system df
    2TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
    3Images          2         2         77.83MB   0B (0%)
    4Containers      3         0         49B       49B (100%)
    5Local Volumes   0         0         0B        0B
    6Build Cache     0         0         0B        0B
    

    docker rmi [OPTIONS] IMAGE [IMAGE…]

    删除一个或多个镜像

    1、删除单个

    1docker rmi -f 镜像ID
    

    2、删除多个

    1docker rmi -f 镜像名1:TAG 镜像名2:TAG
    

    3、删除全部

    1docker rmi -f $(docker images -qa)
    

    面试题:谈谈 Docker 虚悬镜像是什么?

    仓库名、标签都是 <none> 的镜像,俗称虚悬镜像 dangling image

    新建+启动容器

    1docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
    

    1、OPTIONS 说明

    有些是一个减号,有些是两个减号

    --name="容器新名字":为容器指定一个名称

    -d:后台运行容器并返回容器 ID,也即启动守护式容器(后台运行)

    -i:以交互模式运行容器,通常与 -t 同时使用

    -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用

    也即启动交互式容器(前台有伪终端,等待交互)

    -P随机端口映射,大写 P

    -p指定端口映射,小写 p

    2、启动交互式容器(前台命令行)

    1$ docker images
    2REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
    3ubuntu        latest    27941809078c   2 weeks ago    77.8MB
    4hello-world   latest    feb5d9fea6a5   9 months ago   13.3kB
    5$ docker run -it ubuntu /bin/bash
    6root@aeea6c8ac772:/# ps -ef
    7UID        PID  PPID  C STIME TTY          TIME CMD
    8root         1     0  0 05:04 pts/0    00:00:00 /bin/bash
    9root         9     1  0 05:04 pts/0    00:00:00 ps -ef
    

    使用镜像 ubuntu:latest 以交互模式启动一个容器,在容器内执行 /bin/bash 命令:

    1docker run -it ubuntu /bin/bash
    

    参数说明

    -i:交互式操作

    -t:终端

    ubuntuUbuntu镜像

    /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式Shell,因此用的是 /bin/bash

    要退出终端,直接输入 exit

    列出当前所有正在运行的容器

    1docker ps [OPTIONS]
    
    1$ docker ps
    2CONTAINER ID  IMAGE   COMMAND      CREATED        STATUS       PORTS  NAMES
    30de077b13a8b  ubuntu  "/bin/bash"  6 minutes ago  Up 6 minutes        youthful_ja
    

    2、OPTIONS 说明

    -a:列出当前所在正在运行的容器+历史上运行过的容器

    -l:显示最近创建的容器

    -n:显示最近n个创建的容器

    -q静默模式,只显示容器编号

    两种退出方式

    1、exit

    run 进去容器,exit 退出,容器停止

    2、ctrl+p+q

    run 进去容器,ctrl+p+q 退出,容器不停止

    启动已停止运行的容器

    1docker start 容器ID或者容器名
    
    1docker restart 容器ID或者容器名
    
    1docker stop 容器ID或者容器名
    

    强制停止容器

    1docker kill 容器ID或者容器名
    

    删除已停止的容器

    1docker rm 容器ID
    

    危险操作:一次性删除多个容器实例

    1docker rm -f $(docker ps -a -q)
    
    1docker ps -a -q | xargs docker rm
    

    有镜像才能创建容器,这是根本前提(下载一个 Redis:6.0.8 镜像演示)

    启动守护式容器(后台服务器)

    在大部分的场景下,我们希望docker的服务是在后台运行的,我们可以通过 -d 指定容器的后台运行模式。

    1docker run -d 容器名
    

    使用镜像 ubuntu:latest 以后台模式启动一个容器:

    1docker run -d ubuntu
    

    问题:然后 docker ps -a 进行查看,会发现容器已经退出

    很重要的要说明一点:Docker 容器后台运行,就必须有一个前台进程

    容器运行的命令如果不是那些一直挂起的命令(比如运行 toptail),就是会自动退出的。

    这个是 Docker 的机制问题,比如你的 Web 容器,我们以 Nginx 为例,正常情况下,我们配置启动服务只需要启动响应的 service 即可。例如 service nginx start

    但是,这样做,Nginx 为后台进程模式运行,就导致 Docker 前台没有运行的应用,这样的容器后台启动后,会立即自杀,因为它觉得自己没事可做了。

    所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行,常见就是命令行模式,表示我还有交互操作,别中断,O(∩_∩)O哈哈~

    Redis前后台启动演示例子

    ①前台交互式启动

    1docker run -it redis:6.0.8
    

    ②后台守护式启动

    1docker run -d redis:6.0.8
    
    查看容器日志
    1docker logs [OPTIONS] CONTAINER
    
     1$ docker logs 8616a62e0639
     21:C 21 Jun 2022 06:41:38.228 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
     31:C 21 Jun 2022 06:41:38.228 # Redis version=6.0.8, bits=64, commit=00000000, modified=0, pid=1, just started
     41:C 21 Jun 2022 06:41:38.228 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
     51:M 21 Jun 2022 06:41:38.229 * Running mode=standalone, port=6379.
     61:M 21 Jun 2022 06:41:38.229 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
     71:M 21 Jun 2022 06:41:38.229 # Server initialized
     81:M 21 Jun 2022 06:41:38.229 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
     91:M 21 Jun 2022 06:41:38.229 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never').
    101:M 21 Jun 2022 06:41:38.230 * Ready to accept connections
    
    查看容器内运行的进程
    1docker top CONTAINER [ps OPTIONS]
    
    1$ docker top 8616a62e0639
    2UID      PID    PPID   C       STIME       TTY    TIME        CMD
    3polkitd  26537  26518  0       14:41       ?      00:00:02    redis-server *:6379
    
    查看容器内部细节
    1docker inspect [OPTIONS] NAME|ID [NAME|ID...]
    
      1$ docker inspect 8616a62e0639
      4        "Id": "8616a62e06394d8d64fe64ec14396b50990f29480e2805198b0948548770a717",
      5        "Created": "2022-06-21T06:41:37.92007182Z",
      6        "Path": "docker-entrypoint.sh",
      7        "Args": [
      8            "redis-server"
     10        "State": {
     11            "Status": "running",
     12            "Running": true,
     13            "Paused": false,
     14            "Restarting": false,
     15            "OOMKilled": false,
     16            "Dead": false,
     17            "Pid": 26537,
     18            "ExitCode": 0,
     19            "Error": "",
     20            "StartedAt": "2022-06-21T06:41:38.221059032Z",
     21            "FinishedAt": "0001-01-01T00:00:00Z"
     22        },
     23        "Image": "sha256:16ecd277293476392b71021cdd585c40ad68f4a7488752eede95928735e39df4",
     24        "ResolvConfPath": "/var/lib/docker/containers/8616a62e06394d8d64fe64ec14396b50990f29480e2805198b0948548770a717/resolv.conf",
     25        "HostnamePath": "/var/lib/docker/containers/8616a62e06394d8d64fe64ec14396b50990f29480e2805198b0948548770a717/hostname",
     26        "HostsPath": "/var/lib/docker/containers/8616a62e06394d8d64fe64ec14396b50990f29480e2805198b0948548770a717/hosts",
     27        "LogPath": "/var/lib/docker/containers/8616a62e06394d8d64fe64ec14396b50990f29480e2805198b0948548770a717/8616a62e06394d8d64fe64ec14396b50990f29480e2805198b0948548770a717-json.log",
     28        "Name": "/jolly_chatelet",
     29        "RestartCount": 0,
     30        "Driver": "overlay2",
     31        "Platform": "linux",
     32        "MountLabel": "",
     33        "ProcessLabel": "",
     34        "AppArmorProfile": "",
     35        "ExecIDs": null,
     36        "HostConfig": {
     37            "Binds": null,
     38            "ContainerIDFile": "",
     39            "LogConfig": {
     40                "Type": "json-file",
     41                "Config": {}
     42            },
     43            "NetworkMode": "default",
     44            "PortBindings": {},
     45            "RestartPolicy": {
     46                "Name": "no",
     47                "MaximumRetryCount": 0
     48            },
     49            "AutoRemove": false,
     50            "VolumeDriver": "",
     51            "VolumesFrom": null,
     52            "CapAdd": null,
     53            "CapDrop": null,
     54            "CgroupnsMode": "host",
     55            "Dns": [],
     56            "DnsOptions": [],
     57            "DnsSearch": [],
     58            "ExtraHosts": null,
     59            "GroupAdd": null,
     60            "IpcMode": "private",
     61            "Cgroup": "",
     62            "Links": null,
     63            "OomScoreAdj": 0,
     64            "PidMode": "",
     65            "Privileged": false,
     66            "PublishAllPorts": false,
     67            "ReadonlyRootfs": false,
     68            "SecurityOpt": null,
     69            "UTSMode": "",
     70            "UsernsMode": "",
     71            "ShmSize": 67108864,
     72            "Runtime": "runc",
     73            "ConsoleSize": [
     74                0,
     76            ],
     77            "Isolation": "",
     78            "CpuShares": 0,
     79            "Memory": 0,
     80            "NanoCpus": 0,
     81            "CgroupParent": "",
     82            "BlkioWeight": 0,
     83            "BlkioWeightDevice": [],
     84            "BlkioDeviceReadBps": null,
     85            "BlkioDeviceWriteBps": null,
     86            "BlkioDeviceReadIOps": null,
     87            "BlkioDeviceWriteIOps": null,
     88            "CpuPeriod": 0,
     89            "CpuQuota": 0,
     90            "CpuRealtimePeriod": 0,
     91            "CpuRealtimeRuntime": 0,
     92            "CpusetCpus": "",
     93            "CpusetMems": "",
     94            "Devices": [],
     95            "DeviceCgroupRules": null,
     96            "DeviceRequests": null,
     97            "KernelMemory": 0,
     98            "KernelMemoryTCP": 0,
     99            "MemoryReservation": 0,
    100            "MemorySwap": 0,
    101            "MemorySwappiness": null,
    102            "OomKillDisable": false,
    103            "PidsLimit": null,
    104            "Ulimits": null,
    105            "CpuCount": 0,
    106            "CpuPercent": 0,
    107            "IOMaximumIOps": 0,
    108            "IOMaximumBandwidth": 0,
    109            "MaskedPaths": [
    110                "/proc/asound",
    111                "/proc/acpi",
    112                "/proc/kcore",
    113                "/proc/keys",
    114                "/proc/latency_stats",
    115                "/proc/timer_list",
    116                "/proc/timer_stats",
    117                "/proc/sched_debug",
    118                "/proc/scsi",
    119                "/sys/firmware"
    120            ],
    121            "ReadonlyPaths": [
    122                "/proc/bus",
    123                "/proc/fs",
    124                "/proc/irq",
    125                "/proc/sys",
    126                "/proc/sysrq-trigger"
    127            ]
    128        },
    129        "GraphDriver": {
    130            "Data": {
    131                "LowerDir": "/var/lib/docker/overlay2/cc2828def4f62e8de866edbe12655f583a11c586723c20c1fea627f3e8709600-init/diff:/var/lib/docker/overlay2/a8249d070a3c825a941d4d134852fc1aff730a85aee0241ffa2f053b4ad43bcd/diff:/var/lib/docker/overlay2/a5ffdcd005eb951283de7754a3340a747094d52585561a20aa0a83b4ab0e148a/diff:/var/lib/docker/overlay2/32ebaf91ac0fb463c3ecb19fa9db791d2ae6a81f31aa7acb3559f7f5ede0ca72/diff:/var/lib/docker/overlay2/2b77a0daa2495fc17f3b3c7a007b8ea6305f7c5f0e7fd7a7ccca33bdaf56eb3b/diff:/var/lib/docker/overlay2/7e9409453d956f1debe0fe36110ec21aaefaee8bd3eff56e93fe05f022b097b3/diff:/var/lib/docker/overlay2/08f5399c5f34f601b70ace4a2220a653f836d55a0edf4b4d17cb28936120ed14/diff",
    132                "MergedDir": "/var/lib/docker/overlay2/cc2828def4f62e8de866edbe12655f583a11c586723c20c1fea627f3e8709600/merged",
    133                "UpperDir": "/var/lib/docker/overlay2/cc2828def4f62e8de866edbe12655f583a11c586723c20c1fea627f3e8709600/diff",
    134                "WorkDir": "/var/lib/docker/overlay2/cc2828def4f62e8de866edbe12655f583a11c586723c20c1fea627f3e8709600/work"
    135            },
    136            "Name": "overlay2"
    137        },
    138        "Mounts": [
    139            {
    140                "Type": "volume",
    141                "Name": "9b02f82540fec8416f382d3f55496e77fdfcc5ab2b1c3f6e90d380a026b59698",
    142                "Source": "/var/lib/docker/volumes/9b02f82540fec8416f382d3f55496e77fdfcc5ab2b1c3f6e90d380a026b59698/_data",
    143                "Destination": "/data",
    144                "Driver": "local",
    145                "Mode": "",
    146                "RW": true,
    147                "Propagation": ""
    148            }
    149        ],
    150        "Config": {
    151            "Hostname": "8616a62e0639",
    152            "Domainname": "",
    153            "User": "",
    154            "AttachStdin": false,
    155            "AttachStdout": false,
    156            "AttachStderr": false,
    157            "ExposedPorts": {
    158                "6379/tcp": {}
    159            },
    160            "Tty": false,
    161            "OpenStdin": false,
    162            "StdinOnce": false,
    163            "Env": [
    164                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    165                "GOSU_VERSION=1.12",
    166                "REDIS_VERSION=6.0.8",
    167                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.8.tar.gz",
    168                "REDIS_DOWNLOAD_SHA=04fa1fddc39bd1aecb6739dd5dd73858a3515b427acd1e2947a66dadce868d68"
    169            ],
    170            "Cmd": [
    171                "redis-server"
    172            ],
    173            "Image": "redis:6.0.8",
    174            "Volumes": {
    175                "/data": {}
    176            },
    177            "WorkingDir": "/data",
    178            "Entrypoint": [
    179                "docker-entrypoint.sh"
    180            ],
    181            "OnBuild": null,
    182            "Labels": {}
    183        },
    184        "NetworkSettings": {
    185            "Bridge": "",
    186            "SandboxID": "bf61f2e19a43db9d1d4f9fc56ab2000ed702ed91de4da5e776a07e1e31e539dc",
    187            "HairpinMode": false,
    188            "LinkLocalIPv6Address": "",
    189            "LinkLocalIPv6PrefixLen": 0,
    190            "Ports": {
    191                "6379/tcp": null
    192            },
    193            "SandboxKey": "/var/run/docker/netns/bf61f2e19a43",
    194            "SecondaryIPAddresses": null,
    195            "SecondaryIPv6Addresses": null,
    196            "EndpointID": "4c0e86921bef4eb69f04d66c4748c547f2148450854755c37b17f7c6204c996c",
    197            "Gateway": "172.17.0.1",
    198            "GlobalIPv6Address": "",
    199            "GlobalIPv6PrefixLen": 0,
    200            "IPAddress": "172.17.0.2",
    201            "IPPrefixLen": 16,
    202            "IPv6Gateway": "",
    203            "MacAddress": "02:42:ac:11:00:02",
    204            "Networks": {
    205                "bridge": {
    206                    "IPAMConfig": null,
    207                    "Links": null,
    208                    "Aliases": null,
    209                    "NetworkID": "f80509d058b8ad3bbd0032e40431d90ed7197236bf97697680124412c1492bb0",
    210                    "EndpointID": "4c0e86921bef4eb69f04d66c4748c547f2148450854755c37b17f7c6204c996c",
    211                    "Gateway": "172.17.0.1",
    212                    "IPAddress": "172.17.0.2",
    213                    "IPPrefixLen": 16,
    214                    "IPv6Gateway": "",
    215                    "GlobalIPv6Address": "",
    216                    "GlobalIPv6PrefixLen": 0,
    217                    "MacAddress": "02:42:ac:11:00:02",
    218                    "DriverOpts": null
    219                }
    220            }
    221        }
    222    }
    223]
    
    进入正在运行的容器并以命令行交互

    重新进入正在运行的容器有两种方法:

    1docker exec [OPTIONS] CONTAINER COMMAND [ARG...] 
    

    重新进入正在运行的容器中:

    1docker exec -it 8616a62e0639 /bin/bash
    
    1docker attach [OPTIONS] CONTAINER
    

    重新进入正在运行的容器:

    1docker attach 8616a62e0639
    

    上述两种方法的区别

    attach 直接进入容器启动命令的终端,不会启动新的进程。用 exit 退出,会导致容器的停止。

    exec 是在容器中打开新的终端,并且可以启动新的进程。用 exit 退出,不会导致容器的停止。

    推荐使用 docker exec 命令,因为退出容器终端不会导致容器的停止。

    用之前的Redis容器实例进入试试
    1# 进入redis服务
    2docker exec -it 容器ID /bin/bash
    3docker exec -it 容器ID redis-cli
    4# 一般用-d后台启动程序,再用exec进入对应容器实例	
    
     1$ docker ps
     2CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS      NAMES
     371fd743e48fa   redis:6.0.8   "docker-entrypoint.s…"   3 minutes ago   Up 3 minutes   6379/tcp   sleepy_gould
     4$ docker exec -it 71fd743e48fa /bin/bash
     5root@71fd743e48fa:/data# exit
     6exit
     7$ docker exec -it 71fd743e48fa redis-cli
     8127.0.0.1:6379> ping
     9PONG
    10127.0.0.1:6379> set name eric
    11OK
    12127.0.0.1:6379> get name
    13"eric"
    
    从容器内拷贝文件到主机上

    容器-->主机

    1docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
    

    公式:docker cp 容器ID:容器内路径 目的地主机路径

    1、在容器创建文件

    1$ docker exec -it 71fd743e48fa /bin/bash
    2root@71fd743e48fa:/data# cd /tmp
    3root@71fd743e48fa:/tmp# touch a.txt
    4root@71fd743e48fa:/tmp# ls
    5a.txt
    

    2、将文件复制到主机

    1$ docker cp 71fd743e48fa:/tmp/a.txt /root/c.txt
    2$ ls
    3c.txt
    

    主机-->容器

    1docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
    
    导入和导出容器

    1、export 导出容器的内容作为一个 tar 归档文件[对应 import 命令]

    1docker export 容器ID > 文件名.tar
    

    在容器端创建文件 a.txt,并按 ctrl+p+q 退出

    1$ docker run -it ubuntu /bin/bash
    2root@06fa2250f3e6:/# cd
    3root@06fa2250f3e6:~# ls
    4root@06fa2250f3e6:~# clear
    5root@06fa2250f3e6:~# touch a.txt 
    6root@06fa2250f3e6:~# echo "Hello, world!" > a.txt
    7root@06fa2250f3e6:~# // ctrl+p+q 退出界面,不退出进程
    

    在主机端导出整个容器成 tar

    1$ docker export 06fa2250f3e6 > abcd.tar
    2$ ls
    3abcd.tar
    

    2、importtar 包中的内容创建一个新的文件系统再导入为镜像[对应 export]

    1cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
    
     1$ docker ps
     2CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS              PORTS      NAMES
     306fa2250f3e6   ubuntu        "/bin/bash"              About a minute ago   Up About a minute              ecstatic_nobel
     471fd743e48fa   redis:6.0.8   "docker-entrypoint.s…"   About an hour ago    Up About an hour    6379/tcp   sleepy_gould
     5$ docker rm -f 06fa2250f3e6
     606fa2250f3e6
     7$ docker ps
     8CONTAINER ID   IMAGE         COMMAND                  CREATED       STATUS       PORTS      NAMES
     971fd743e48fa   redis:6.0.8   "docker-entrypoint.s…"   2 hours ago   Up 2 hours   6379/tcp   sleepy_gould
    10$ cat abcd.tar | docker import - ashley/ubuntu:1.0.0
    11sha256:daa7fecb01e3e80143aa665fbc41abcc683d8531eeae4387598f84ad1a1d5fa9
    12$ docker ps
    13CONTAINER ID   IMAGE         COMMAND                  CREATED       STATUS       PORTS      NAMES
    1471fd743e48fa   redis:6.0.8   "docker-entrypoint.s…"   2 hours ago   Up 2 hours   6379/tcp   sleepy_gould
    15$ docker images
    16REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
    17ashley/ubuntu   1.0.0     daa7fecb01e3   16 seconds ago   77.8MB
    18ubuntu          latest    27941809078c   2 weeks ago      77.8MB
    19hello-world     latest    feb5d9fea6a5   9 months ago     13.3kB
    20redis           6.0.8     16ecd2772934   20 months ago    104MB
    21$ docker run -it daa7fecb01e3 /bin/bash
    22root@ae152bad6453:/# cd
    23root@ae152bad6453:~# ls
    24a.txt
    25root@ae152bad6453:~# cat a.txt
    26Hello, world!
    27root@ae152bad6453:~# 
    

    Docker镜像

    镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是 image 镜像文件。

    只有通过这个镜像文件才能生成 Docker 容器实例(类似 Gonew 出来一个对象)。

    分层的镜像

    镜像是分层的,以我们的 pull 为例,在下载过程中我们可以看到 Docker 的镜像好像是在一层一层的下载。

     1$ docker pull mysql
     2Using default tag: latest
     472a69066d2fe: Pulling fs layer 
     593619dbc5b36: Pull complete 
     699da31dd6142: Pull complete 
     7626033c43d70: Pull complete 
     837d5d7efb64e: Extracting [==================================================>]     149B/149B
     9ac563158d721: Download complete 
    10d2ba16033dad: Download complete 
    11688ba7d5c01a: Download complete 
    1200e060b6d11d: Downloading [===================>                               ]     42MB/105.2MB
    131c04857f594f: Download complete 
    144d7cfa90e6ea: Download complete 
    15e0431212d27d: Download complete
    

    UnionFS(联合文件系统)

    UnionFS 是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同且目录挂载到同一个虚拟文件系统下 「unite several directories into a single virtual filesystem」。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

    特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

    Docker镜像加载原理

    Docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统叫 UnionFS

    bootfsboot file system 」主要包含 bootloaderkernelbootloader 主要是引导加载 kernelLinux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是引导文件系统 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs

    rootfsroot file system 」,在 bootfs 之上,包含的就是典型 Linux 系统中的 /dev/proc/bin/etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 UbuntuCentOS 等等。

    平时我们安装进虚拟机的 Ubuntu 都是好几个G,为什么 Docker 这里才 77.8M

    1$ docker images ubuntu
    2REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
    3ubuntu       latest    27941809078c   2 weeks ago   77.8MB
    

    对于一个精简的OSrootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用 Hostkernel,自己只需要提供 rootfs 就行了。由此可见对于不同的 Linux 发行版,bootfs 基本是一致的,rootfs 会有差别,因此不同的发行版可以公用 bootfs

    为什么Docker镜像要采用这种分层结构呢

    采用镜像分层最大的一个好处就是共享资源,方便复制迁移。之所以采用这种分层结构为的就是方便复用。

    比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了,而且镜像的每一层都可以共享。

    Docker镜像层都是只读的,容器层是可写的

    当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作”容器层”,”容器层”之下的都叫”镜像层”。

    所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器层钟。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

    Docker镜像commit操作案例

    docker commit提交容器副本使之成为一个新的镜像

    1docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
    

    案例演示ubuntu安装vim

    1、从 Hub 上下载 ubuntu 镜像到本地并成功运行

    2、原始的默认 ubuntu 镜像是不带着 vim 命令的

    3、外网连通的情况下,安装 vim

     1$ docker run -it ubuntu /bin/bash
     2root@f840a57094ad:/# vim a.txt
     3bash: vim: command not found
     4root@b06b07b5c64f:/# apt-get update
     5Get:1 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]
     6......                             
     7Fetched 21.6 MB in 13s (1675 kB/s)  
     8Reading package lists... Done
     9root@f840a57094ad:/# apt-get -y install vim
    10Reading package lists... Done
    11......
    12Processing triggers for libc-bin (2.35-0ubuntu3) ...
    

    4、安装完成后,commit 成自己的新镜像

    1$ docker commit -m="vim cmd add ok" -a="ashley" f840a57094ad imw7/myubuntu:1.1
    2sha256:1e9b0351af1f8fe4a7863a4cfd0b0d1146fdfae61f8ea56d0fcdef9c1ba73f3c
    3$ docker images
    4REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
    5imw7/myubuntu   1.1       1e9b0351af1f   30 seconds ago   180MB
    6ubuntu          latest    27941809078c   2 weeks ago      77.8MB
    

    5、启动新镜像并和原来的对比

     1$ docker images
     2REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
     3imw7/myubuntu   1.1       1e9b0351af1f   11 minutes ago   180MB
     4ubuntu          latest    27941809078c   2 weeks ago      77.8MB
     5$ docker run -it ubuntu /bin/bash
     6root@ec7727e9390c:/# vim a.txt
     7bash: vim: command not found
     8root@ec7727e9390c:/# exit
     9exit
    10$ docker run -it 1e9b0351af1f /bin/bash
    11root@0e3310eed3ba:/# vim a.txt
    12root@0e3310eed3ba:/# cat a.txt
    13This is Docker!
    

    Docker 中的镜像分层,支持通过扩展现有镜像,创建新的镜像。类似 Java 继承于一个 Base 基础类,自己再按需扩展。

    新镜像是从 base 镜像一层一层叠加生成的,每安装一个软件,就在现有镜像的基础上增加一层。

    本地镜像素材原型

    1$ docker images
    2REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
    3imw7/myubuntu   1.1       1e9b0351af1f   11 minutes ago   180MB
    

    阿里云开发者平台

    https://promotion.aliyun.com/ntms/act/kubernetes.html

    创建仓库镜像

    1、选择控制台,进入容器镜像服务

    使用 docker tag 命令重命名镜像,并将它通过专有网络地址推送至Registry。

    1$ docker images
    2REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
    3imw7/myubuntu   1.1       1e9b0351af1f   19 hours ago    180MB
    4$ docker tag 1e9b0351af1f registry.cn-shenzhen.aliyuncs.com/imw7/myubuntu:1.1
    

    使用 docker push 命令将该镜像推送至远程。

    1docker push registry.cn-shenzhen.aliyuncs.com/imw7/myubuntu:1.1
    

    将阿里云上的镜像下载到本地

    1docker pull registry.cn-shenzhen.aliyuncs.com/imw7/myubuntu:1.1
    

    本地镜像发布到私有库

    本地镜像发布到私有库流程

    1、官方 Docker Hub 地址:https://hub.docker.com/,中国大陆访问太慢了且有被阿里云取代的趋势,不太主流。

    2、Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及公司机密的不可能提供镜像给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。

    Docker Registry

    Docker Registry 是官方提供的工具,可以用于构建私有镜像仓库。

    将本地镜像推送到私有库

    下载镜像Docker Registry

    1docker pull registry
    

    运行私有库Registry,相当于本地有个私有Docker Hub

    1docker run -d -p 5000:5000 -v /root/myregistry/:/tmp/registry --privileged=true registry
    

    默认情况下,仓库被创建在容器的 /var/lib/registry 目录下,建议自行用容器卷映射,方便于宿主机联调。

    案例演示创建一个新镜像,ubuntu安装ifconifg命令

    1、从 Hub 上下载 Ubuntu 镜像到本地并成功运行

    1docker pull ubuntu
    

    2、原始的 Ubuntu 镜像是不带 ifconfig 命令的

    1$ docker run -it ubuntu /bin/bash
    2root@fa41e46960f0:/# ifconfig
    3bash: ifconfig: command not found
    

    3、外网连通的情况下,安装 ifconfig 命令并测试通过

    Docker 容器内执行下述两条命令

    1apt-get update
    2apt-get install net-tools
    

    ② 测试通过

     1root@fa41e46960f0:/# ifconfig
     2eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
     3        inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255
     4        ether 02:42:ac:11:00:03  txqueuelen 0  (Ethernet)
     5        RX packets 8987  bytes 22503087 (22.5 MB)
     6        RX errors 0  dropped 0  overruns 0  frame 0
     7        TX packets 8949  bytes 769069 (769.0 KB)
     8        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    10lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
    11        inet 127.0.0.1  netmask 255.0.0.0
    12        loop  txqueuelen 1000  (Local Loopback)
    13        RX packets 0  bytes 0 (0.0 B)
    14        RX errors 0  dropped 0  overruns 0  frame 0
    15        TX packets 0  bytes 0 (0.0 B)
    16        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    ctrl+p+q 退出,执行后续操作。

    4、安装完成后,commit 自己的新镜像

    1docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
    
    1docker commit -m="ifconfig cmd add" -a="ashley" fa41e46960f0 imw7/myubuntu:1.2
    

    curl验证私服库上有什么镜像

    1curl -XGET http://宿主机IP地址:5000/v2/_catalog
    

    通过 ifconfig 可以查看宿主机IP地址

    1$ curl -XGET http://172.30.108.127:5000/v2/_catalog
    2{"repositories":[]} // 空的
    

    将新镜像 imw7/myubuntu:1.2 修改符合私服规范的Tag

    按照公式:

    1docker tag 镜像:Tag Host:Port/Repository:Tag
    

    :填写自己的 host 主机 IP 地址

    使用命令docker tagimw7/myubuntu:1.2这个镜像修改为172.30.108.127:5000/imw7/myubuntu:1.2

    1$ docker tag imw7/myubuntu:1.2 172.30.108.127:5000/imw7/myubuntu:1.2
    2$ docker images
    3REPOSITORY                            TAG       IMAGE ID       CREATED          SIZE
    4172.30.108.127:5000/imw7/myubuntu     1.2       def83a58fbd8   53 minutes ago   114MB
    5imw7/myubuntu                         1.2       def83a58fbd8   53 minutes ago   114MB
    

    修改配置文件使之支持http

    由于 Docker 默认不允许 http 方式推送镜像,通过配置选项来取消这个限制。

    1$ cat /etc/docker/daemon.json
    3  "registry-mirrors": ["https://wivds1wh.mirror.aliyuncs.com"]
    

    使用 vim 命令新增内容:vim /etc/docker/daemon.json

    2 "registry-mirrors": ["https://wivds1wh.mirror.aliyuncs.com"], 3 "insecure-registries":["172.30.108.127:5000"]

    注:修改后如果不生效,建议重启 Docker

    push推送到私服库

    1docker push 172.30.108.127:5000/imw7/myubuntu:1.2
    

    curl验证私服库上有什么镜像2

    1$ curl -XGET http://172.30.108.127:5000/v2/_catalog
    2{"repositories":["imw7/myubuntu"]}
    

    pull到本地并运行

    1、删除本地的镜像文件

    1$ docker images
    2REPOSITORY                          TAG   IMAGE ID       CREATED       SIZE
    3172.30.108.127:5000/imw7/myubuntu   1.2   def83a58fbd8   2 hours ago   114MB
    4imw7/myubuntu                       1.2   def83a58fbd8   2 hours ago   114MB
    5...
    6$ docker rmi -f 172.30.108.127:5000/imw7/myubuntu:1.2
    7$ docker rmi -f imw7/myubuntu:1.2
    

    2、拉取到本地

    1docker pull 172.30.108.127:5000/imw7/myubuntu:1.2
    
    1$ docker images
    2REPOSITORY                                        TAG       IMAGE ID       CREATED         SIZE
    3imw7/myubuntu                                     1.2       def83a58fbd8   2 hours ago     114MB
    4172.30.108.127:5000/imw7/myubuntu                 1.2       def83a58fbd8   2 hours ago     114MB
    
     1$ docker run -it 172.30.108.127:5000/imw7/myubuntu:1.2 /bin/bash
     2root@93472ebdd6c2:/# ifconfig
     3eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
     4        inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255
     5        ether 02:42:ac:11:00:03  txqueuelen 0  (Ethernet)
     6        RX packets 7  bytes 586 (586.0 B)
     7        RX errors 0  dropped 0  overruns 0  frame 0
     8        TX packets 0  bytes 0 (0.0 B)
     9        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    11lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
    12        inet 127.0.0.1  netmask 255.0.0.0
    13        loop  txqueuelen 1000  (Local Loopback)
    14        RX packets 0  bytes 0 (0.0 B)
    15        RX errors 0  dropped 0  overruns 0  frame 0
    16        TX packets 0  bytes 0 (0.0 B)
    17        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    Docker容器数据卷

    :容器卷记得加入 --privileged=true

    Docker 挂载主机目录访问如果出现 cannot open directory .: Permission denied,怎么解决呢?

    解决办法:在挂载目录后多加一个 --privileged=true 参数即可。

    如果是 CentOS7 安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为。

    SELinux 里面挂载目录被禁止掉了,如果要开启,一般使用 --privileged=true 命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,Container 内的 root 拥有真正的 root 权限,否则,Container 内的 root 只是外部的一个普通用户权限。

    卷就是目录或文件,存在于一个或多个容器中,由 Docker 挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System 提供一些用于持续存储或共享数据的特性。

    卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此 Docker 不会在容器删除时删除其挂载的数据卷。

    1、一句话:有点类似 Redis 里面的 rdbaof 文件

    2、将 Docker 容器内的数据保存进宿主机的磁盘中

    3、运行一个带有容器卷存储功能的容器实例

    1docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
    

    将运用与运行的环境打包镜像,run 后形成容器实例运行,但是对数据的要求希望是持久化的。

    Docker 容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。为了能保存数据在 Docker 中我们使用卷。

    1、数据卷可在容器之间共享或重用数据

    2、卷中的更改可以直接实时生效

    3、数据卷中的更改不会包含在镜像的更新中

    4、数据卷的生命周期一直持续到没有容器使用它为止

    数据卷案例

    宿主vs容器之间映射添加容器卷

    直接命令添加
    1docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
    

    Docker 中创建命名为 u1Ubuntu 镜像,并实现文件的映射:

    1$ docker run -it --privileged=true -v /tmp/host_data:/tmp/docker_data --name=u1 ubuntu
    2root@10f4b9049f6f:/# cd /tmp/docker_data/
    3root@10f4b9049f6f:/tmp/docker_data# ls
    4root@10f4b9049f6f:/tmp/docker_data# touch dockerin.txt
    5root@10f4b9049f6f:/tmp/docker_data# ls
    6dockerin.txt
    

    在宿主机的对应目录中,可以实时查看到刚刚在 Docker 中创建的文件:

    1$ cd /tmp/host_data/
    2$ ls
    3dockerin.txt
    

    同样的,在主机创建文件,也可以实时在 Docker 容器中获得对应的文件。

    查看数据卷是否挂载成功

    可以通过如下命令,查看数据卷是否挂载成功

    1docker inspect 容器ID
    

    举个例子:

     1$ docker ps 
     2CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
     310f4b9049f6f   ubuntu    "bash"    15 minutes ago   Up 15 minutes             u1
     4$ docker inspect 10f4b9049f6f
     7        ...
     8        "Mounts": [
    10                "Type": "bind",
    11                "Source": "/tmp/host_data",
    12                "Destination": "/tmp/docker_data",
    13                "Mode": "",
    14                "RW": true,
    15                "Propagation": "rprivate"
    17        ],
    18        ...
    

    通过 docker inspect 命令查看 Mounts 模块判断是否数据卷挂载成功。

    容器和宿主机之间数据共享

    首先在宿主机停掉正在运行的容器。

    1$ docker ps
    2CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
    310f4b9049f6f   ubuntu    "bash"    29 minutes ago   Up 29 minutes             u1
    4$ docker stop 10f4b9049f6f
    510f4b9049f6f
    6$ docker ps
    7CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    

    在宿主机的 /tmp/host_data/ 文件夹下写入文件。

    1$ cd /tmp/host_data/
    2$ ls
    3$ touch c.txt
    4$ ls
    5c.txt  dockerin.txt  hostin.txt
    

    然后在宿主机重新启动刚停止的容器。

    1$ docker start 10f4b9049f6f
    210f4b9049f6f
    3$ docker exec -it 10f4b9049f6f /bin/bash
    4root@10f4b9049f6f:/# cd /tmp/docker_data/
    5root@10f4b9049f6f:/tmp/docker_data# ls
    6c.txt  dockerin.txt  hostin.txt
    

    可以看到在容器停止运行的情况下,在宿主机写入的数据,当容器重新运行后也能够同步。

    Docker 修改,主机同步获得

    主机修改,Docker 同步获得

    Docker 容器 stop,主机修改,Docker 容器重启后也能同步获得

    读写规则映射添加说明

    读写(默认)
    1docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
    

    默认就是 rw,因此可以省略。

    如果要让容器实例内部被限制,只能读取不能写,可以通过 /容器内目录:ro 镜像名,实现功能:

    1docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
    

    注:ro = read only

    1$ docker run -it --privileged=true -v /mydocker/u:/tmp:ro ubuntu
    2root@b7d1f80b47c5:/# cd /tmp
    3root@b7d1f80b47c5:/tmp# ls
    4root@b7d1f80b47c5:/tmp# touch c.txt
    5touch: cannot touch 'c.txt': Read-only file system
    

    可以看出,在容器内写入内容失败,因为是只读的文件系统。

    此时如果宿主机写入内容,可以同步给容器内,容器可以读取到。

    宿主机写入内容:

    1$ cd /mydocker/u/
    2$ ls
    3$ touch a.txt
    4$ ls
    5a.txt
    

    容器内可以读到:

    1root@b7d1f80b47c5:/tmp# ls
    2a.txt
    

    卷的继承和共享

    1、容器1完成和宿主机的映射

    1$ docker run -it --privileged=true -v /mydocker/u:/tmp --name u1 ubuntu
    2root@5a8ae43aa393:/# cd /tmp
    3root@5a8ae43aa393:/tmp# ls
    4root@5a8ae43aa393:/tmp# touch u1_data.txt
    5root@5a8ae43aa393:/tmp# ls
    6u1_data.txt
    
    1$ cd /mydocker/u
    2$ ls
    3u1_data.txt
    

    2、容器2继承容器1的卷规则

    1docker run -it --privileged=true --volumes-from 父类 --name u2 ubuntu
    
    1$ docker run -it --privileged=true --volumes-from u1 --name u2 ubuntu
    2root@43f70de5eb61:/# cd /tmp
    3root@43f70de5eb61:/tmp# ls
    4u1_data.txt
    5root@43f70de5eb61:/tmp# touch u2_data.txt
    6root@43f70de5eb61:/tmp# ls
    7u1_data.txt  u2_data.txt
    
    1$ cd /mydocker/u/
    2$ ls
    3u1_data.txt  u2_data.txt
    

    :停掉容器1,容器2也能和宿主机互联互通。恢复容器1之后,容器2和宿主机在容器1停掉期间产生的数据也能在容器1中同步。

    Docker常规安装简介

    1docker search [OPTIONS] TERM
    
    1docker pull [OPTIONS] NAME[:TAG|@DIGEST]
    
    1docker images [OPTIONS] [REPOSITORY[:TAG]]
    
    1docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
    
    服务端口映射

    格式:-p port:port

    1docker run -d -p 6379:6379 redis:6.0.8
    
    1docker stop [OPTIONS] CONTAINER [CONTAINER...]
    
    1docker rm [OPTIONS] CONTAINER [CONTAINER...]
    

    安装Tomcat

    DockerHub上面查找Tomcat镜像

    1$ docker search tomcat
    2NAME    DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    3tomcat  Apache Tomcat is an open source implementati…   3344      [OK]             
    4...
    

    从DockerHub上拉取Tomcat到本地

    1docker pull tomcat
    

    查看是否有拉取到的Tomcat

    1$ docker images tomcat
    2REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
    3tomcat       latest    fb5657adc892   6 months ago   680MB
    

    使用Tomcat镜像创建容器实例(也叫运行镜像)

    1docker run -d -p 8080:8080 tomcat
    

    -p:小写,主机端口:docker容器端口

    -P:大写,随机分配端口

    i:交互

    t:终端

    d:后台

    1$ docker run -d -p 8080:8080 --name t1 tomcat
    2788f39f0635eb7925652422217a9c6273f970926c55aef15d17c0c3d9d95ee6a
    3$ docker ps
    4CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                                       NAMES
    5788f39f0635e   tomcat    "catalina.sh run"   12 seconds ago   Up 11 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   t1
    

    访问猫首页

    因为新版设置,导致无法访问。

    1、可能没有映射端口或者没有关闭防火墙

    因为是在阿里云云服务器 ECS 上的 Docker 里安装的 Tomcat,所以需要访问 120.77.71.67:8080需要在安全组中放开8080端口

    2、把 webapps.dist 目录换成 webapps

  • 先成功启动 Tomcat
  • 1$ docker ps
    2CONTAINER ID   IMAGE     COMMAND             CREATED         STATUS         PORTS                                       NAMES
    3788f39f0635e   tomcat    "catalina.sh run"   6 minutes ago   Up 6 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   t1
    4$ docker exec -it t1 /bin/bash
    5root@788f39f0635e:/usr/local/tomcat# 
    
  • 查看 webapps 文件夹,为空
  • 1root@788f39f0635e:/usr/local/tomcat# cd webapps
    2root@788f39f0635e:/usr/local/tomcat/webapps# ls -l
    3total 0
    
  • webapps.dist 目录换成 webapps
  • 1root@788f39f0635e:/usr/local/tomcat/webapps# cd ..
    2root@788f39f0635e:/usr/local/tomcat# rm -r webapps
    3root@788f39f0635e:/usr/local/tomcat# mv webapps.dist webapps
    

    修改完成后,可成功访问 Tomcat 首页。

    免修改版说明

    1docker pull billygoo/tomcat8-jdk8
    2docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8
    

    使用特定版本可以免去最新版的修改过程,简化构建程序。

    DockerHub上查找MySQL镜像

    1$ docker search mysql
    2NAME    DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    3mysql   MySQL is a widely used, open-source relation…   12767     [OK] 
    4...
    

    从DockerHub上(阿里云加速器)拉取MySQL5.7镜像到本地

    1$ docker pull mysql:5.7
    2$ docker images mysql:5.7
    3REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
    4mysql        5.7       c20987f18b13   6 months ago   448MB
    

    使用MySQL5.7镜像创建容器(也叫运行镜像)

    参见 DockerHub 官网MySQL界面

    1、使用 MySQL 镜像

     1$ docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
     265ae64574e4e6b301cb30744156d1c46b14e24a6e89f6d01943939da566689e8
     3$ docker ps
     4CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
     565ae64574e4e   mysql:5.7   "docker-entrypoint.s…"   18 seconds ago   Up 17 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   objective_satoshi
     6$ docker exec -it 65ae64574e4e /bin/bash
     7root@65ae64574e4e:/# mysql -uroot -p
     8Enter password: 
     9Welcome to the MySQL monitor.  Commands end with ; or \g.
    10Your MySQL connection id is 2
    11Server version: 5.7.36 MySQL Community Server (GPL)
    12...
    13mysql>
    

    2、建库表插入数据

     1mysql> show databases;
     2+--------------------+
     3| Database           |
     4+--------------------+
     5| information_schema |
     6| mysql              |
     7| performance_schema |
     8| sys                |
     9+--------------------+
    104 rows in set (0.00 sec)
    12mysql> create database db01;
    13Query OK, 1 row affected (0.00 sec)
    15mysql> use db01;
    16Database changed
    17mysql> create table t1(id int, name varchar(20));
    18Query OK, 0 rows affected (0.03 sec)
    20mysql> insert into t1 values(1, 'z3');
    21Query OK, 1 row affected (0.01 sec)
    23mysql> select * from t1;
    24+------+------+
    25| id   | name |
    26+------+------+
    27|    1 | z3   |
    28+------+------+
    291 row in set (0.00 sec)
    

    3、外部使用 Navicat 连接运行在 Docker 上的 MySQL 容器实例服务

    和下图一样填入正确的 「主机IP地址」,「MySQL 端口号」,「用户名」和「密码」。点击「测试连接」,如果弹出「连接成功」窗口的,即表明连接是通的。点击 「确定」即可实现 NavicatDocker 中的 MySQL容器的连接。

    UbuntuNavicat无限试用的方法

    1sudo rm -rf ~/.config/navicat
    2sudo rm -rf ~/.config/dconf/user
    4sudo lsof | grep navicat | grep \\.config
    

    删除以上文件,即可无限试用Navicat Premium 16

    插入中文报错

    可以看出,编码有所不同,Docker 中文字体默认编码为 latin1。需要将它修改为 utf8 编码,中文才能正常插入和显示。

    删除容器后,里面的MySQL数据怎么办

    容器实例一删除,mysql 数据也会丢失。

    1root@65ae64574e4e:/# exit
    2exit
    3$ docker ps
    4CONTAINER ID   IMAGE       COMMAND                  CREATED             STATUS             PORTS                                                  NAMES
    565ae64574e4e   mysql:5.7   "docker-entrypoint.s…"   About an hour ago   Up About an hour   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   objective_satoshi
    6$ docker rm -f 65ae64574e4e
    765ae64574e4e
    8$ docker ps
    9CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    

    这是很显然的道理,容器被删除后,容器里面的 MySQL 也就被删除了,数据自然消失了。

    1、新建 MySQL 容器实例

    1docker run -d -p 3306:3306 --privileged=true -v /data/mysql/mysql/log:/var/log/mysql -v /data/mysql/mysql/data:/var/lib/mysql -v /data/mysql/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql --restart always mysql:5.7
    

    实现 Docker 上的 mysql 数据同步到宿主机的功能。

    2、新建 my.cnf

    通过容器卷同步给 mysql 容器实例,解决中文字符编码问题。

    将下面的配置代码写入 my.cnf 文件中,可以将中文编码改为 utf8

    1[client]
    2default_character_set=utf8
    3[mysqld]
    4collation_server = utf8_general_ci
    5character_set_server = utf8
    

    在宿主机进行如下操作:

    1$ cd /data/mysql/conf/
    2$ ls
    3$ vim my.cnf
    4$ cat my.cnf
    5[client]
    6default_character_set=utf8
    7[mysqld]
    8collation_server = utf8_general_ci
    9character_set_server = utf8
    

    3、重新启动 MySQL 容器实例再重新进入并查看字符编码

     1$ docker restart mysql
     2mysql
     3$ docker ps
     4CONTAINER ID  IMAGE      COMMAND  CREATED        STATUS         PORTS   NAMES
     58044e666f6ff  mysql:5.7  ...      3 minutes ago  Up 8 seconds   ...     mysql
     6$ docker exec -it 8044e666f6ff /bin/bash
     7root@8044e666f6ff:/# mysql -uroot -p
     8Enter password: 
     9...
    11mysql> SHOW VARIABLES LIKE 'character%';
    12+--------------------------+----------------------------+
    13| Variable_name            | Value                      |
    14+--------------------------+----------------------------+
    15| character_set_client     | utf8                       |
    16| character_set_connection | utf8                       |
    17| character_set_database   | utf8                       |
    18| character_set_filesystem | binary                     |
    19| character_set_results    | utf8                       |
    20| character_set_server     | utf8                       |
    21| character_set_system     | utf8                       |
    22| character_sets_dir       | /usr/share/mysql/charsets/ |
    23+--------------------------+----------------------------+
    

    可以看到字符集编码从 latin1 修改为了 utf8

    4、再新建库新建表再插入中文测试

    5之后的DB有效,需要新建

    结论:Docker 安装完 MySQLrun 出容器后,建议先修改完字符集编码,再新建mysql库-表-插数据

    1mysql> create database db02;
    2mysql> use db02;
    3mysql> create table t1(id int, name varchar(20));
    

    6、假如将当前容器实例删除,再重新来一次,之前建的 db01 还有吗?

    答案是有的。重新启动一个 mysql 容器,进入数据库查看数据,因为挂载了容器数据卷,所以数据会从宿主机中恢复到当前 Docker 容器中。

     1$ docker run -d -p 3306:3306 --privileged=true -v /data/mysql/mysql/log:/var/log/mysql -v /data/mysql/mysql/data:/var/lib/mysql -v /data/mysql/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql --restart always mysql:5.7
     23944d05f9ef3dad023b77dc2626a2ff0ca7db02a71cab875c478a3ff7021cf1b
     3$ docker ps
     4CONTAINER ID  IMAGE      COMMAND                 CREATED        STATUS        PORTS                                                 NAMES
     53944d05f9ef3  mysql:5.7  "docker-entrypoint.s…"  3 seconds ago  Up 3 seconds  0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp  mysql
     6$ docker exec -it mysql /bin/bash
     7root@3944d05f9ef3:/# mysql -uroot -p
     8Enter password: 
     9...
    10mysql> use db01;
    11Reading table information for completion of table and column names
    12You can turn off this feature to get a quicker startup with -A
    14Database changed
    15mysql> select * from t1;
    16+------+--------+
    17| id   | name   |
    18+------+--------+
    19|    1 | z3     |
    20|    2 | li4    |
    21|    3 | 王五   |
    22+------+--------+
    233 rows in set (0.00 sec)
    

    安装Redis

    Dokcer Hub 上(阿里云加速器)拉取 Redis 镜像到本地标签为 6.0.8

    1docker pull redis:6.0.8
    
     1$ docker run -d -p 6379:6379 redis:6.0.8
     2165eb674ce4fa94494958a77e179fe7f8a933b01acaf3897dc8c7e7e9e39eeff
     3$ docker ps
     4CONTAINER ID  IMAGE        COMMAND                 CREATED        STATUS        PORTS                                      NAMES
     5165eb674ce4f  redis:6.0.8  "docker-entrypoint.s…"  5 seconds ago  Up 4 seconds  0.0.0.0:6379->6379/tcp, :::6379->6379/tcp  amazing_chebyshev
     6$ docker exec -it 165eb674ce4f /bin/bash
     7root@165eb674ce4f:/data# redis-cli
     8127.0.0.1:6379> ping
     9PONG
    10127.0.0.1:6379> set k1 v1
    11OK
    12127.0.0.1:6379> get k1
    13"v1"
    14127.0.0.1:6379>
    

    命令提醒:容器卷记得加入–privileged=true

    Docker 挂在主机目录 Docker 访问出现cannot open directory .: Permission denied

    解决办法:在挂载目录后多加一个 --privileged=true 参数即可。

    CentOS 宿主机下新建目录 /data/redis

    1mkdir -p /data/redis
    

    拷贝配置文件

    将准备好的 redis.conf 文件放进宿主机的 /tmp 目录,默认出厂的原始 redis.conf

    1cp /tmp/redis.conf /data/redis/
    

    修改配置文件

    /data/redis 目录下修改 redis.conf 文件:

    1、开启 Redis 验证(可选)

    1requirepass foobared
    

    2、允许 Redis 外地连接

    注释掉 bind 127.0.0.1

    1# bind 127.0.0.1
    

    3、daemonize no

    daemonize yes 注释掉或设置为 daemonize no,因为该配置和 docker run-d 参数冲突,会导致一直启动失败。

    1# daemonize yes
    2# 或
    3daemonize no
    

    4、开启 Redis 数据持久化(可选)

    1appendonly yes
    

    使用 redis:6.0.8 镜像创建容器(也叫运行镜像):

    1$ docker run -p 6379:6379 --name myrds --restart always --privileged=true -v /data/redis/redis.conf:/etc/redis/redis.conf -v /data/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
    2d8a9a2a820193a31675fcacec2ced5e025b5f22dc63634637e4e5a86e2a1b2b8
    3$ docker ps
    4CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS          PORTS                                       NAMES
    5d8a9a2a82019   redis:6.0.8   "docker-entrypoint.s…"   24 seconds ago   Up 23 seconds   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   myrds
    

    测试redis-cli连接

     1$ docker ps
     2CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS          PORTS                                       NAMES
     3d8a9a2a82019   redis:6.0.8   "docker-entrypoint.s…"   24 seconds ago   Up 23 seconds   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   myrds
     4$ docker exec -it myrds /bin/bash
     5root@d8a9a2a82019:/data# redis-cli -a password
     6Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
     7127.0.0.1:6379> ping
     8PONG
     9127.0.0.1:6379> set k1 v1
    10OK
    11127.0.0.1:6379> get k1
    12"v1"
    13127.0.0.1:6379> 
    

    请证明Docker启动使用了自己指定的配置文件

    1$ docker exec -it myrds /bin/bash
    2root@d8a9a2a82019:/data# redis-cli -a password
    3Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    4127.0.0.1:6379> select 15
    

    这里用的配置文件,数据库默认是 16 个。

    :修改后记得重启服务。

    1# 宿主机/app/redis/redis.conf
    2# Set the number of databases. The default database is DB 0, you can select
    3# a different one on a per-connection basis using SELECT <dbid> where
    4# dbid is a number between 0 and 'databases'-1
    5databases 10
    

    宿主机的修改会同步给 Docker 容器里面的配置。

     1$ docker restart myrds
     2myrds
     3$ docker ps
     4CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS         PORTS                                       NAMES
     5d8a9a2a82019   redis:6.0.8   "docker-entrypoint.s…"   23 minutes ago   Up 7 seconds   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   myrds
     6$ docker exec -it myrds /bin/bash
     7root@d8a9a2a82019:/data# redis-cli -a password
     8Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
     9127.0.0.1:6379> get k1
    10"v1"
    11127.0.0.1:6379> select 15
    12(error) ERR DB index is out of range
    

    安装Nginx

    Docker 进阶指南 Portainer