docker(一)介绍与基础命令

docker(一)介绍与基础命令

之前介绍过什么是docker,这里说点细节的

Docker 包括三个基本概念:
镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。
容器与镜像的关系类似于面向对象编程中的对象与类。
在这里插入图片描述

概念说明
Docker 镜像(Images)Docker 镜像是用于创建 Docker 容器的模板,比如 centos系统。
Docker 容器(Container)容器是独立运行的一个或一组应用,是镜像运行时的实体。
Docker 客户端(Client)Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
Docker 主机(Host)一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker Registry1.Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。2.Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。3.一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。4.通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
Docker MachineDocker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。

安装

rpm包下载
# 阿里云开源镜像站:https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/
# 官方站点:https://docs.docker.com/ https://docs.docker.com/install/linux/docker-ce/centos/
# 二者下载皆可 但是阿里云更快一些


自动安装命令如下:
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
也可以使用国内 daocloud 一键安装命令:
curl -sSL https://get.daocloud.io/docker | sh
手动安装
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 device-mapper-persistent-data lvm2
#yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 
#device-mapper-persistent-data 和 lvm2。

3.添加软件源
#采用的是阿里云的源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

4.安装
yum install docker-ce docker-ce-cli containerd.io
#containerd.io -守护进程与操作系统API(在本例中是LXC-Linux容器)接口,本质上是将Docker与操作系统分离,还为非Docker容器管理器提供容器服务
#docker-ce -docker守护进程,这是完成所有管理工作的部分,需要Linux上的另外两个
#docker ce cli -cli工具来控制守护进程,如果你想控制一个远程docker守护进程,你可以自己安装它们 
#如果提示您接受 GPG 密钥,请选是。

4.1如果启用了多个 Docker 仓库,则在未在 yum install 或
 yum update 命令中指定版本的情况下,进行的安装或更新将始终安装
 最高版本,这可能不适合您的稳定性需求。

#列出并排序您存储库中可用的版本。此示例按版本号(从高到低)对结果进行排序。
yum list docker-ce --showduplicates | sort -r

#通过其完整的软件包名称安装特定版本,该软件包名称是软件包名称
#(docker-ce)加上版本字符串(第二列),从第一个冒号(:)
#一直到第一个连字符,并用连字符(-)分隔。
#例如:docker-ce-18.09.1。
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

5.启动 Docker
systemctl start docker 
docker version
docker run hello-world
#通过运行 hello-world 映像来验证是否正确安装

加速

国内从 DockerHub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如:

网易:https://hub-mirror.c.163.com/
阿里云:https://<你的ID>.mirror.aliyuncs.com
七牛云加速器:https://reg-mirror.qiniu.com

当配置某一个加速器地址之后,若发现拉取不到镜像,请切换到另一个加速器地址。国内各大云服务商均提供了 Docker 镜像加速服务,建议根据运行 Docker 的云平台选择对应的镜像加速服务。

阿里云镜像获取地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors,登陆后,左侧菜单选中镜像加速器就可以看到你的专属地址了:

对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):

{"registry-mirrors":["https://reg-mirror.qiniu.com/"]}
#"自己的加速地址"

systemctl daemon-reload
systemctl restart docker


"""
解决“警告”问题:
docker info
可以看到
WARNING: IPv4 forwarding is disabled
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

cd /etc/sysctl.d
# 过滤内核参数 将这些改成 1
sysctl -a | grep forwarding
sysctl -a | grep bridge

怎么改:
在当前目录下
vim docker.conf
inet.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.all.mc_forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.default.mc_forwarding = 1
net.ipv4.conf.docker0.forwarding = 1
net.ipv4.conf.docker0.mc_forwarding = 1
net.ipv4.conf.eth0.forwarding = 1
net.ipv4.conf.eth0.mc_forwarding = 1
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.lo.mc_forwarding = 1
net.bridge.bridge-nf-call-ip6tables = 1

sysctl --system #使其立即生效

"""

文件目录与镜像结构

# docker的所有数据都存放在此
[root@docker docker]# ls
builder   containers  network   plugins   swarm  trust
buildkit  image       overlay2  runtimes  tmp    volumes
[root@docker docker]# pwd
/var/lib/docker

docker镜像
镜像是docker容器的基石,容器是镜像的运行实例,有了镜像才能启动容器
[root@foundation0 ~]# docker images rhel7
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rhel7               latest              0a3eb3fde7fd        4 years ago         140 MB

为什么一个rhel7只有140MB

"""
linux操作系统由内核空间和用户空间组成(rootfs bootfs)
内核空间是kernel,linux刚启动的时候会加载bootfs文件系统,之后bootfs会被卸载掉
用户空间的文件系统是rootfs,包括我们熟悉鹅/dev,/proc,/bin 等目录
对于base镜像来说,底层直接用host的kernel,自己只需要提供rootfs就行了
而对于一个精简版的os,rootfs可以很小,只需要包括最基本的命令,工具和程序就可以了
"""
# base镜像提供的是最小安装的Linux发行版本
# 支持运行多种Linux OS 不同的Linux发行版的区主要就是rootfs 
#比如Ubuntu 使用upstat 管理服务 apt管理软件包 ,
#而centos 7 使用systemd和yum 这些都是用户空间上的区别 
#linux kernel差别不大

##注意:容器的内核版本和宿主机的版本是一致的
##可通过:uname -r来看

##所有容器都共用host的kernel,在容器中没办法对kernel升级,
#如果容器对kernel有要求(比如某个应用只能在某个kernel版本下运行),
#则不建议用容器,这种场景虚拟机更适合

#镜像的分层结构

docker支持通过扩展现有镜像,创建新的镜像
实际上,docker hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的。
新的镜像是从base镜像一层一层叠加生成的,每安装一个软件,就在现有的基础增加一层。

#为什么docker镜像要采用这种分层结构呢?
"""
最大的一个好处是:共享资源
比如:有多个镜像都从相同的base镜像构建而来,
那么docker host只需在磁盘上保存一份base镜像:同时内存中也只需加载一份base镜像,
就可以为所有容器服务了,而其镜像的每一层都可以被共享
那么一个疑问是:如果多个容器共享一份基础镜像,
当某个容器修改了基础镜像的内容,比如/etc下的文件,
这时其他容器的/etc是否也会被修改???
答案是不会
修改会被限制在单个容器内
这就是我们接下来要学习的容器copy-on-write特性
"""

可写的容器层
当容器启动时,一个新的可写层被加载到镜像的顶部
这一层通常被叫做“容器层”,“容器层”之下的都叫“镜像层”
所有对容器的改动,无论添加,删除,还是修改文件都只会发生在容器层,只有容器层是可写的,容器层下面的所有镜像层都是只读的
#注意:一个镜像层最多127层(镜像层最好不要太多)

#具体细节
"""
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统,
如果不同层中有一个相同路径的文件,比如/a,上层的/a会覆盖下层的/a,
也就是说用户只能访问到山层中的文件/a,在容器层中,
用户看到的是一个叠加之后的文件系统
1.添加文件,在容器中创建文件时,新文件被添加到容器层中
2.读取文件,在容器中读取某个文件时,docker会从上往下依次在各个镜像层中查找到此文件,一旦找到,打开并读入内存
3.修改文件,在容器中修改已经存在的文件时,docker会从上往下依次在各个镜像层中查找到此文件,
一旦找到,立即将其复制到容器层,然后修改
4.删除文件,在容器中删除文件时,docker也是从上往下依次在镜像层中查找此文件,找到后,会在容器层中记录下此删除操作
"""
##只有当修改的时候才复制一份数据,这种特性被称作copy-on-write,可见,
#容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,
所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享


docker run -it --name ubuntu  
#-it 以交互式模式开启一个终端

# 我们可以看到容器和虚拟机共享内核
# 到底怎么共享的呢?
[root@docker docker]# hostnamectl 
   Static hostname: docker
         Icon name: computer-vm
           Chassis: vm
        Machine ID: e26d28698aed47fb9ec897d00ec96f27
           Boot ID: 4f549a312dff439b80de72c1c74a0682
    Virtualization: kvm
  Operating System: Red Hat Enterprise Linux Server 7.5 (Maipo)
       CPE OS Name: cpe:/o:redhat:enterprise_linux:7.5:GA:server
            Kernel: Linux 3.10.0-862.el7.x86_64
      Architecture: x86-64
      
[root@server3 sysctl.d]# docker run -it --name vm1 ubuntu 
#run:创建并运行一个容器 -it:以交互式的形式 --name:给容器起个名字 ubuntu:镜像名称
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7413c47ba209: Pull complete 
0fe7e7cbb2e8: Pull complete 
1d425c982345: Pull complete 
344da5c95cec: Pull complete 
Digest: sha256:c303f19cfe9ee92badbbbd7567bc1ca47789f79303ddcef56f77687d4744cd7a
Status: Downloaded newer image for ubuntu:latest
Try 'uname --help' for more information.
root@b16f9eaab99e:/# uname -r  
#可以见得 docker是对我们操作系统内核有一定的要求的
3.10.0-514.el7.x86_64

[root@docker docker]# docker run -it --name vm1 ubuntu 
root@4154d58490f2:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
root@4154d58490f2:/# touch file1 #改变的是容器层 
root@4154d58490f2:/# touch file2
#但是,如果我们只是运行容器,然后退出不保存容器的话,容器中我们
#所做的工作是不会被保存和持久化的。

总结一下
"""
1.共享宿主机的kernel
2.base镜像提供的是最小的linux发行版
3.同一docker主机支持运行多种linux发行版
4.采用分层结构的最大好处是:共享资源
"""

"""
Copy-on-Write可写容器层
容器层意所有镜像层都是只读的
docker从上往下依次查找文件
容器层保存镜像变换的部分 并不会对镜像本身进行任何修改
一个镜像最多127层
"""

命令

docker command --help 

容器使用

#获取镜像
如果我们本地没有 ubuntu 镜像,我们可以使用 docker pull 命令来载入 ubuntu 镜像:
docker pull ubuntu

运行容器

docker run 命令来在容器内运行一个应用程序。

docker run ubuntu:15.10 /bin/echo "Hello world"
各个参数解析:

    docker: Docker 的二进制执行文件。

    run: 与前面的 docker 组合来运行一个容器。

    ubuntu:15.10 指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。

    /bin/echo "Hello world": 在启动的容器里执行的命令
以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。


#运行交互式的容器
docker 的两个参数 -i -t,让 docker 运行的容器实现"对话"的能力:
runoob@runoob:~$ docker run -i -t ubuntu:15.10 /bin/bash
root@0123ce188bd8:/#

各个参数解析:

    -t: 在新容器内指定一个伪终端或终端。

    -i: 允许你对容器内的标准输入 (STDIN) 进行交互。

注意第二行 root@0123ce188bd8:/
#,此时我们已进入一个 ubuntu15.10 系统的容器
我们尝试在容器中运行命令 cat /proc/version和ls分别查看当前系统的版本信息和当前目录下的文件列表

exit 命令或者使用 CTRL+D 来退出容器


#启动容器(后台模式)
docker run -itd --name ubuntu-test ubuntu /bin/bash
#加了 -d 参数默认不会进入容器,想要进入容器需要使用指令 docker exec(下面会介绍到)。


runoob@runoob:~$ docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"
2b1b7a428627c51ab8810d541d759f072b4fc75487eed05812646b8534a2fe63

在输出中,我们没有看到期望的 "hello world",而是一串长字符
这个长字符串叫做容器 ID,对每个容器来说都是唯一的,我们可以通过容器 ID 来查看对应的容器发生了什么。
首先,我们需要确认容器有在运行,可以通过 docker ps 来查看:

runoob@runoob:~$ docker ps
CONTAINER ID        IMAGE                  COMMAND              ...  
5917eac21c36        ubuntu:15.10           "/bin/sh -c 'while t…"    ...

输出详情介绍:
CONTAINER ID: 容器 ID。
IMAGE: 使用的镜像。
COMMAND: 启动容器时运行的命令。
CREATED: 容器的创建时间。
STATUS: 容器状态。

'状态有7种:
    created(已创建)
    restarting(重启中)
    running(运行中)
    removing(迁移中)
    paused(暂停)
    exited(停止)
    dead(死亡)'

PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。
NAMES: 自动分配的容器名称。
在宿主主机内使用 docker logs 命令,查看容器内的标准输出:
docker logs 2b1b7a428627
docker logs amazing_cori

停止容器

我们使用 docker stop 命令来停止容器:
docker stop 2b1b7a428627

通过 docker ps 查看,容器已经停止工作:

runoob@runoob:~$ docker ps

可以看到容器已经不在了。
也可以用下面的命令来停止:
runoob@runoob:~$ docker stop amazing_cori

#启动已停止运行的容器
docker ps -a
docker start b750bbbcfd88 

docker stop <容器 ID>
docker restart <容器 ID>


进入容器

在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:
    docker attach
    docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。

#attach 命令
docker attach 1e560fca3906 
#如果从这个容器退出,会导致容器的停止。

#exec 命令
docker exec -it 243c32535da7 /bin/bash
#如果从这个容器退出,不会导致容器的停止

导出/入容器

#导出容器

如果要导出本地某个容器,可以使用 docker export 命令。
docker export 1e560fca3906 > ubuntu.tar
#导出容器 1e560fca3906 快照到本地文件 ubuntu.tar。

#导入容器快照
可以使用 docker import 从容器快照文件中再导入为镜像
cat docker/ubuntu.tar | docker import - test/ubuntu:v1
#将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:

也可以通过指定 URL 或者某个目录来导入,例如:
docker import http://example.com/exampleimage.tgz example/imagerepo

删除容器

删除容器使用 docker rm 命令:

docker rm -f 1e560fca3906

下面的命令可以清理掉所有处于终止状态的容器。
docker container prune 

web容器的应用

#在docker容器中运行一个 Python Flask 应用来运行一个web应用。
docker pull training/webapp  # 载入镜像
docker run -d -P training/webapp python app.py
参数说明:
    -d:让容器在后台运行。
    -P:将容器内部使用的网络端口随机映射到我们使用的主机上。

#查看 WEB 应用容器
使用 docker ps 来查看我们正在运行的容器:

docker ps
CONTAINER ID        IMAGE               COMMAND             ...        PORTS                 
d3d5e39ed9d3        training/webapp     "python app.py"     ...        0.0.0.0:32769->5000/tcp

Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32769 上。
这时我们可以通过浏览器访问WEB应用
ip:32769

我们也可以通过 -p 参数来设置不一样的端口:
docker run -d -p 5000:5000 training/webapp python app.py

docker ps
CONTAINER ID        IMAGE                             PORTS                     NAMES
bf08b7f2cd89        training/webapp     ...        0.0.0.0:5000->5000/tcp    wizardly_chandrasekhar
d3d5e39ed9d3        training/webapp     ...        0.0.0.0:32769->5000/tcp   xenodochial_hoov
#容器内部的 5000 端口映射到我们本地主机的 5000 端口上。

网络端口的快捷方式

通过 docker ps 命令可以查看到容器的端口映射,docker 还提供了另一个快捷方式 docker port,使用 docker port 可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。
上面我们创建的 web 应用容器 ID 为 bf08b7f2cd89 名字为 wizardly_chandrasekhar。
我可以使用 docker port bf08b7f2cd89 或 docker port wizardly_chandrasekhar 来查看容器端口的映射情况。

docker port bf08b7f2cd89
5000/tcp -> 0.0.0.0:5000

docker port wizardly_chandrasekhar
5000/tcp -> 0.0.0.0:5000

查看日志

docker logs [ID或者名字] 可以查看容器内部的标准输出。

docker logs -f bf08b7f2cd89
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.239.1 - - [09/May/2016 16:30:37] "GET / HTTP/1.1" 200 -
192.168.239.1 - - [09/May/2016 16:30:37] "GET /favicon.ico HTTP/1.1" 404 -

-f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
从上面,我们可以看到应用程序使用的是 5000 端口并且能够查看到应用程序的访问日志。

查看进程与底层信息

我们还可以使用 docker top 来查看容器内部运行的进程

runoob@runoob:~$ docker top wizardly_chandrasekhar
UID     PID         PPID          ...       TIME                CMD
root    23245       23228         ...       00:00:00            python app.py
使用 docker inspect 来查看 Docker 的底层信息。
它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。

runoob@runoob:~$ docker inspect wizardly_chandrasekhar
[
    {
        "Id": "bf08b7f2cd897b5964943134aa6d373e355c286db9b9885b1f60b6e8f82b2b85",
        "Created": "2018-09-17T01:41:26.174228707Z",
        "Path": "python",
        "Args": [
            "app.py"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 23245,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2018-09-17T01:41:26.494185806Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
......


停止与重启

#停止 WEB 应用容器
docker stop wizardly_chandrasekhar   
wizardly_chandrasekhar

#重启WEB应用容器
已经停止的容器,我们可以使用命令 docker start 来启动。
docker start wizardly_chandrasekhar
wizardly_chandrasekhar

docker ps -l 查询最后一次创建的容器:
docker ps -l 
CONTAINER ID        IMAGE                             PORTS                     NAMES
bf08b7f2cd89        training/webapp     ...        0.0.0.0:5000->5000/tcp    wizardly_chandrasekhar

#正在运行的容器,我们可以使用 docker restart 命令来重启。

#我们可以使用 docker rm 命令来删除不需要的容器
runoob@runoob:~$ docker rm wizardly_chandrasekhar  
wizardly_chandrasekhar

#删除容器时,容器必须是停止状态,否则会报如下错误
#或者rm -f
runoob@runoob:~$ docker rm wizardly_chandrasekhar
Error response from daemon: You cannot remove a running container bf08b7f2cd897b5964943134aa6d373e355c286db9b9885b1f60b6e8f82b2b85. Stop the container before attempting removal or force remove

命令大全

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值