docker基本操作

2018-06-21 Vaniot 更多博文 » 博客 » GitHub »

docker

原文链接 https://vaniot-s.github.io/2018/06/21/docker%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


预操作

加速器

修改/etc/docker/daemon.json 文件并添加上 registry-mirrors键值,将镜像源切换为国内。

    $ vim /etc/docker/daemon.json 
    {
    "registry-mirrors": ["https://registry.docker-cn.com"]
    }

设置权限

docker守护进程启动的时候,会默认赋予名字为docker的用户组读写Unix socket的权限,创建docker用户组,并将当前用户加入到docker用户组中,当前用户就有权限访问Unix socket了,就可以执行docker相关命令.

    sudo groupadd docker     #添加docker用户组
    sudo gpasswd -a $USER docker     #将登陆用户加入到docker用户组中
    newgrp docker     #更新用户组
    docker ps    #测试docker命令是否可以使用sudo正常使用

<!--more-->

镜像

Docker镜像由佷多的层次构成,使用Union FS将不同的层结合到一个镜像中。

获取镜像

docker获取镜像的命令:

    docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] #默认的仓库地址为Docker Hub,仓库名为两段式名称,即 <用户名>/<软件名>

    docker pull ubuntu:18.04

运行

已获取的镜像,作为容器的基础启动

    docker run -it --rm --name ubuntu ubuntu:18.04 bash #run 启动容器 -i 交互操作 -t 终端 --rm 容器退出后会立即删除 --name 命名为ubuntu bash进入shell

查看镜像

  • 列出已经下载的镜像

      docker image ls # 列表包含了 仓库名、标签、镜像 ID、创建时间 以及 所占用的空间
    

    镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个标签

  • 查看镜像的体积

      docker system shell  #查看镜像、容器、数据卷所占用的空间
    

    镜像仓库中显示的为压缩后的体积,远大于本地的镜像的体积,除此之外,镜像是多层存储结构,可以继承,复用,不同的镜像使用相同的镜像,故拥有共同的层,实际镜像的占用空间或许会比列表中的占用要小。

  • 虚悬镜像 当下载已存在的镜像时,原有的镜像的名会被转移到新的镜像,旧有的镜像仓库名、标签均为<none>,被称做为虚悬镜像(dangling image)

      docker image ls -f dangling=true #只查看虚悬镜像
      docker image prune #删除虚悬镜像
    
  • 中间层镜像 docker的中间层镜像,是为了加速镜像的构建,重复利用资源,中间层镜像也没有标签,会随着依赖它的镜像删除而被删除。

    docker image ls -a # 查看中间层镜像
    
  • 镜像过滤(列出部分镜像) 依据条件列出镜像 --filter(简写为:-f)过滤器参数

    docker image ls ubuntu # 根据仓库名列出镜像
    docker image ls ubuntu:18.04 #根据指定的仓库名和标签列出镜像
    docker image ls -f since=ubnutu:18.04 #列出在ubuntu:18.04之后创建的镜像
    docker image lf -f before=ubuntu:18.04 # 列出在ubuntu:18.04之前创建的镜像
    docker image ls -f label=test #根据Label 过滤,如果镜像创建时定义了
    
  • 特定的格式显示 利用参数筛选出镜像的特定的信息,或使用go的模板语法go的模板语法 指定显示的镜像的信息。

    docker image ls  -q # 只显示镜像的id
    docker image ls  --format "{{.ID}]: {{.Repository}}" #直接列出镜像结果,并且只包含镜像ID和仓库名
    docker imagels --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" #以表格等距显示,并且有标题行,和默认一样,自己定义列
    

    删除镜像

    删除本地镜像

    docker image rm --help #查看删除的命令参数
    docker image rm [OPTIONS] IMAGE [IMAGE...] 
    #Aliases: rm, rmi, remove
    #Options: 
    #   -f, --force Force removal of the image
    #   --help       Print usage 
    #   --no-prune   Do not delete untagged parents
    docker image rm 501 #使用镜像的短id删除镜像
    docker image rm centos #使用镜像名(<仓库名>:<标签>)删除镜像
    docker image ls --digests #查看镜像并列出摘要
    docker image rm  node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228 #使用镜像摘要删除镜像
    

    Untagged 和 Deleted

    删除标签镜像时,首先会将目标镜像的标签取消,当还有其他的标签指向该镜像时,并不会执行Delete操作。当镜像的层被其他镜像依赖,或有以该镜像为基础的容器,均不会触发Delete操作。

    使用docker image ls 配合删除

    根据查询的结果成批的删除镜像列表

    docker image rm $(docker image ls -q redis)
    docker image rm $(docker image ls -q -f before =mongo:3.2)
    

    CentOS/RHEL 的用户需要注意的事项 ??? 详见

镜像的构成

docker可用于定制镜像,但一般不用于定制镜像,docker commit会将上一层的镜像跟随当前的存储成而变得臃肿,docker commit生成的尽享对于其他是黑箱操作,不可重复。docker commit一般用于入侵后的现场的保护。

  docker run --name webserver -d -p 8099:80 nginx
  #启动 nginx 容器并将其映射到本地的8099端口 用浏览器打开http:localhost:8099 输出 welcome to Nginx
  docker exec -it webserver bash #交互的方式进入容器

  #修改页面的内容
  root@b406af708fb8:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  root@b406af708fb8:/# exit
  #用浏览器打开http:localhost:8099 输出 Hello Docker
  docker diff webserver #查看具体的改动
  docker commit --help #查看 commit 的参数
  # docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
  # Create a new image from a container's changes
  # Options:
  #   -a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
  #   -c, --change list      Apply Dockerfile instruction to the created image (default [])
  #       --help             Print usage
  #   -m, --message string   Commit message
  #   -p, --pause            Pause container during commit (default true)

  docker commit -a "vaniot a developer" -m "change the content of index.html" webserver nginx:v2.0 #提交生成新的镜像
  docker history nginx:v2.0 #查看nginx:v2.0的变化

Dockerfie定制镜像

Dockerfile概述

Dockerfile是一个文本文件,但不同于shell,包含了许多的指令,每一个指令都将会建立一层。将需要定制的镜像的每一层修改,安装,构建,操作的命令都写入其中。解决重复构建、构建的透明性及体积。

从dcoker引擎中获取

  • FROM 指定基础镜像

FROMDockerfile指定了镜像的基础,之后的操作均在其的基础之上进行。

Docker中存在一个空白的镜像名为scratch,以此镜像为基础,则说明之后的指令将作为镜像的第一层开始。

  FROM scratch
  • RUN 执行命令

RUN用于执行命令的两种格式:

* shell:`RUN<命令>`,类似与命令行中输入命令
  ```shell
  RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  ```
* exec: RUN ["可执行文件", "参数1", "参数2"]

ps: 每一个RUN都会创建一层,对于一层中不使用多个RUN,Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障更为容易。镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉.

  FROM debian:jessie

  RUN buildDeps='gcc libc6-dev make' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps #执行清理工作

example: 构建nginx

    mkdir nginx #构建空的文件夹
    cd nginx 
    touch Dockerfile 
    #在Dockerfile中写入
    FROM nginx
    RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
    #构建镜像
    docker build -t nginx:v3 . #构建镜像 `.`不能缺少
    docker run  -d -p 8099:80 nginx:v3.0 #创建容器

在docker中.指定了上下文, 对于'docker build'的原理,Docker 运行是分为Docker引擎(服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API( Docker Remote API),客户端工具通过API与Docker引擎交互。使用的远程调用形式在服务端(Docker 引擎)完成。docker build命令在服务端构建镜像。用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

从Git repo中构建

   docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14  

指定构建所需的 Git repo,并且指定默认的 master 分支,构建目录为 /8.14/,然后 Docker 自己去 git clone 这个项目、切换到指定分支、并进入到指定目录后开始构建。

使用 tar压缩包构建

   docker build http://server/context.tar.gz

Docker 引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建。

标准输入中读取 Dockerfile 进行构建

   docker build - < Dockerfile # cat Dockerfile | docker build -

标准输入中读取上下文压缩包进行构建

   docker build - < context.tar.gz

Dockerfile指令详解

  • Copy复制文件

格式有如下两种:

  • COPY <源路径> ... <目标路径>(类似于命令行)
  • COPY "<源路径1>",... "<目标路径>" <源路径>可以是多个或者满足Go[filepath.Match](https://golang.org/pkg/path/filepath/#Match)规则的通配符,<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。 shell COPY package.json /usr/src/app/ #将构建上下文目录中<源路径>的文件/目录复制到新一层的镜像内的<目标路径>位置 COPY hom* /mydir/ COPY hom?.txt /mydir/ > 使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。
    • ADD 复制文件

ADDCOPY 的格式和性质基本一致,ADD可执行更加复杂的更能,ADD允许<源路径>URLDocker引擎会下载该链接的文件到<目标文件>并将权限设置为600(若要修改权限需要额外的加一层RUN进行权限的修改),对于下载的压缩包,解压也需要一层RUN指令进行解压(<源路径>为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到<目标路径>去)

   FROM scratch
   ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz / #自动解压ubuntu镜像

ADD 指令会令镜像构建缓存失效,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。

  • CMD 容器的启动

容器是一个进程,容器中的应用均应该以前台执行,CMD用于指定默认的容器主进程的启动命令。CMD的两种格式:

  • shell:CMD <命令>
  • exec : CMD [“可执行文件”,"参数1","参数2",...] #解析时会被解析为JSON数组,使用时必须为双引号。 shell #Dockerfile FROM ubuntu:16.04 RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/* CMD [ "curl", "-s", "http://ip.cn" ] #build docker build -t myip 。 #run docker run myip #输出当前IP的地址 docker run myip curl -s http://ip.cn -i #覆盖掉之前的CMD 增加http头信息
    • ENTRYPOINT

ENTRYPOINT指定容器启动程序及参数,也可通过在docker run时指定参数--entrypoint修改已经指定的EMTRYPOINT容器启动程序及参数。

  #Dockerfile
  FROM ubuntu:16.04
  RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
  ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
  #build 
  docker build  -t ip .
  #run 
  docker run ip
  docker run it -i #修改ENTRYPOINT的内容
  • ENV环境变量 ENV设置环境变量,其值可在其他指令中使用,设置环境变量的格式如下:

    • ENV <key><value>
    • ENV <key1>=<value1> <key2>=<value2>... shell ENV NODE_VERSION 8.11.4 RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \ && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \ && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs
  • ARG 构建参数

ARG的作用与ENV相同,用于设置环境变量,但ARG设置的是构建环境变量,在容器运行时不会存在这些环境变量。docker history可以看到ARG的值。Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。格式:

  ARG <参数名>[=<默认值>]

该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值>来覆盖。

  • VOLUME定义匿名卷

容器运行时,对于数据库类需要保存数据的应用,其数据哭文件应该保存于卷中,对于容器存储层不发生写操作。

  #Dockerfile
  VOLUME /data #将/data指定为匿名卷
  #docker run
  docker run -d -v mydata:/data xxx # 运行将mydata卷挂在到/data 
  • EXPOSE 声明端口 EXPOSE声明运行是容器提供的服务端口,声明容器打算使用的端口,不会在运行时开启该端口的服务,不会自动在宿主进行端口映射。当docker run -P会自动随机映射EXPOSE的端口。格式: shell EXPOSE <端口1> [<端口2>...] > 运行时使用-p <宿主端口>:<容器端口>,-p映射宿主端口和容器端口,将容器的对应端口服务公开给外界访问。
  • WORKDIR 指定工作目录

WORKDIR指定工作目录,以后的各层的当前目录就被改为指定的目录,如果目录不存在,WORKDIR会建立目录,改变环境状态并影响以后的层。如果需要改变以后各层的工作目录的位置,那么应该使用WORKDIR指令。

  • USER 指定当前用户

USER改变之后层执行RUN,CMDENTRYPOINT命令的身份。

  # 建立 redis 用户,并使用 gosu 换另一个用户执行命令
  RUN groupadd -r redis && useradd -r -g redis redis
  # 下载 gosu
  RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" \
  && chmod +x /usr/local/bin/gosu \
  && gosu nobody true
  # 设置 CMD,并以另外的用户执行
  CMD [ "exec", "gosu", "redis", "redis-server" ] #以redis 的身份执行
  • HEALTHCHECK 健康检查

HEALTHCHECK检查容器的状态是否正常,镜像在指定了 HEALTHCHECK指令后,用其启动容器,通过docker container ls可以查看,初始状态会为 starting,在HEALTHCHECK指令检查成功后变为healthy,如果连续一定次数失败,则会变为unhealthy。命令格式:

- `HEALTHCHECK [选项] CMD <命令>:`设置检查容器健康状况的命令
- `HEALTHCHECK NONE:`如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

对于[选项的设置]

- `--interval=<间隔>:`两次健康检查的间隔,默认为30s
- `--timeout=<时长>:` 检查命令运行超时时间,超过时间默认为30,检查失败
- `--retries=<次数>:`当连续失败指定次数后,将容器状态视为`unhealthy`

```shell
#Dockerfile
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
#build
docker build -t healthcheck:v1 .
#run
docker run -d -name web -p 8100:80 healthcheck:v1
# container ls
docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                  NAMES
5f3d26567fb4        healthcheck:v1      "nginx -g 'daemon ..."   12 seconds ago      Up 10 seconds (healthy)   0.0.0.0:8100->80/tcp   web
```
`docker inspect`查看检查命令的输出:
```shell
docker inspect --format '{{json .State.Health}}' web | python -m json.tool #输出最近5条检查信息

{
  "FailingStreak": 0,
  "Log": [
    {
        "End": "2018-08-24T15:49:19.185224539+08:00",
        "ExitCode": 0,
        "Output": "<!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n    body {\n        width: 35em;\n        margin: 0 auto;\n        font-family: Tahoma, Verdana, Arial, sans-serif;\n    }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
        "Start": "2018-08-24T15:49:19.147078923+08:00"
    },
    ...
  ], 
  "Status": "healthy"
}
```
  • ONBUILD ??

ONBUILD之后跟随着其它的指令,这些指令会在以当前镜像为基础镜像时,去构建下一级镜像才会被执行,当前镜像中不会执行,即为下一级的镜像准备。

Dockerfile多阶段构建

  #Dockerfile
  FROM golang:1.9-alpine as builder #命名为builder的第一阶段
  RUN apk --no-cache add git
  WORKDIR /go/src/github.com/go/helloworld/
  RUN go get -d -v github.com/go-sql-driver/mysql
  COPY app.go .
  RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
  FROM alpine:latest as prod
  RUN apk --no-cache add ca-certificates
  WORKDIR /root/
  COPY --from=0 /go/src/github.com/go/helloworld/app . #从上一阶段复制文件
  CMD ["./app"]
  #build
  docker build -t go/helloworld:3 .
  #构建其中一阶段的镜像
  docker build --target builder -t username/imagename:tag .

从镜像中复制文件:

  COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

* Dockerfile 最佳实践文档

容器

DockerAUFS上构建的容器,容器是独立运行的一个或一组应用,以及它们的运行态环境。

启动容器

基于镜像新建容器

新建并启动容器dcoker run,

  # docker run 的命令格式
  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

  docker run ubuntu:16.04 /bin/echo "Hello World" #输出一个"Hello world",之后终止容器
  docker run -t -i ubuntu:16.04 /bin/bash #启动一个客户端,允许用户进行交互

使用docker run会进行如下操作:

  • 检查本地是否存在指定的镜像,不存在从公有的仓库
  • 利用镜像创建并启动一个容器
  • 分配一个文件系统,并在只读的镜像文件层外面挂载一层可读写层
  • 从宿主机配置的网桥接口中一个虚拟的接口到容器
  • 从地址池配置一个IP地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被终止 shell docker run -d ubuntu:16.04 /bin/sh -c "while true; do echo hello world; sleep 1; done" #容器会在后台运行并不会把输出的结果 (STDOUT) 打印到宿主机上(输出结果可以用 docker logs 查看) #### 将终止的容器重新启动 docker container start将一个已经停止的容器启动运行。 docker container restart将运行状态的容器重新启动。 ### 终止容器 docker container stop终止一个运行的容器。 ### 进入容器 当其东容器时 带有参数-d,容器启动后会进入后台,进入守护态的容器使用dcoker attach或者docker exec命令, #### attach ```shell docker container ls #查看容器 # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 5f3d26567fb4 healthcheck:v1 "nginx -g 'daemon ..." 2 days ago Up About an hour (healthy) 0.0.0.0:8100->80/tcp web

docker attach web #进入名为web的容器 #exit时,会导致容器的停止。

#### `exec`
  `docker exec`可以有多个参数,
  ```shell
  docker  run -dit  healthcheck:v1
  b5897d0132
  docker exec -it b5897 #exit时,容器不会停止

容器的导入及导出

导出容器

将本地的容器导出,使用docker export

   docker export b5897d > healty.tar #将容器快照导出

导入容器快照

使用docker import从容器快照文件中导入为镜像,

cat healthy.tar | docker import - test/healthcheck:v1.0

通过指定 URL 或者某个目录来导入,例如

 docker import http://example.com/exampleimage.tgz example/imagerepo

删除容器

使用docker container rm来删除一个处于终止状态的容器。

 docker container rm  trusting_newton

清理所有处于终止状态的容器

docker container prune

仓库

在注册服务器(Registry:管理仓库的具体服务器)上可以有多个仓库,每个仓库下有多个镜像。

拉取及推送镜像

查找官方仓库中的镜像

  docker search php #--filter=stars=N 参数指定仅显示收藏数量为 N 以上的镜像
  docker pull php #拉取镜像到本地
  docker tag php:5.6 vaniot/php:5.6 #在登陆后将本地的镜像退送到docker hub

自动创建

私有仓库

docker-registry官方提供用于构建私有的镜像仓库,

  • 容器运行 获取官方的registry镜像来运行,默认仓库建在容器的/var/lib/registry目录下。 shell docker run -d -p 5000:5000 -v -v /opt/data/registry:/var/lib/registry registry #将上传的镜像放到 /opt/data/registry
  • 私有仓库进行操作 创建好私有仓库后,使用docker tag标记一个镜像,推送到仓库。 shell # 查看本机已有的镜像 docker image ls docker tag IMAGE[:TAG] [REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG] #将镜标记到本地 docker tag ubuntu:latest 127.0.0.1:5000/ubuntu:latest #推送镜像 docker push 127.0.0.1:5000/ubuntu:latest #查看本地的镜像 curl 127.0.0.1:5000/v2/_catalog {"repositories":["ubuntu"]} #删除镜像 docker image rm 127.0.0.1:5000/ubuntu:latest #从私有仓库中下载镜像 docker pull 127.0.0.1:5000/ubuntu:latest ## 数据管理 对于容器而言数据管理的两中方式:
  • 数据卷(Volumes)
  • 挂载主机目录(Bind mounts) ### 数据卷 (Volumes) 数据卷是一个可供一个或多个容器使用的特殊目录,理解为多个容器共享的文件目录,与宿主机,容器无关,绕过了UFS,数据卷设计用于持久化数据,其生命周期独立于容器,数据卷不会在容器被删除后自动删除数据卷
  • 数据卷可以在容器之间共享和重用
  • 数据卷的修改会立即生效
  • 数据卷的改变不会影响到镜像
  • 数据卷默认会一直存在,即使容器被删除 #### 数据卷的操作 shell # 数据卷的创建 docker volume create volume-test # 查看所有的数据卷 docker volume ls #查看制定数据卷的详细信息 docker volume inspect volume-test # [ # { # "CreatedAt": "2018-08-30T23:16:20+08:00", # "Driver": "local", # "Labels": {}, # "Mountpoint": "/var/lib/docker/volumes/volume-test/_data", # "Name": "volume-test", # "Options": {}, # "Scope": "local" # } # ] #### 容器中使用数据卷 容器中挂载数据卷,使用--mount标记将数据卷挂载到容器里,docker run时可以挂载多个数据卷shell docker run -d -P --name web --mount source=volume-test,target=/webapp training/webapp python app.py #创建一个名为 web 的容器,并加载一个 数据卷 到容器的 /webapp 目录。 docker inspect web # #mount 的信息 # "Mounts": [ # { # "Type": "volume", # "Name": "volume-test", # "Source": "/var/lib/docker/volumes/volume-test/_data", # "Destination": "/webapp", # "Driver": "local", # "Mode": "z", # "RW": true, # "Propagation": "" # } # ], #### 删除数据卷 shell docker volume rm volume-test #删除数据卷 docker rm -v #删除容器时并删除数据卷 docker volume prune #清理数据卷 ### 挂载主机目录 docker挂载目录可以使用--mount-v指定一个本地主机的目录挂载到容器中去。当本地不存在指定的文件,-v的指令会在本地创建文件夹,而--mount则会报错。 shell #使用--mount挂载文件 docker run -d -P --name web --mount type=bind,source=/src/webapp,target=/opt/webapp training/webapp python app.py # 使用-v 挂载文件 docker run -d -P --name web -v /src/webapp:/opt/webapp:ro --mount type=bind,source=/src/webapp, target=/opt/webapptraining/webapp python app.py > Docker挂载宿主机目录默认权限为读写,当增加指令为readonly则为只读 shell docker run -d -P \ --name web \ # -v /src/webapp:/opt/webapp:ro \ --mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \ training/webapp \ python app.py ## 网络 ### 外部访问容器 当外部需要访问容器中的网络应用,通过-p-P指定端口映射。使用-PDOcker会随机映射一个49000-49900的端口到内部容器开放的网络端口。 #### 映射所有接口地址 使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行 shell $ docker run -d -p 5000:5000 training/webapp python app.py 此时默认会绑定本地所有接口上的所有地址。 #### 映射到指定地址的指定端口 可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1 shell $ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py #### 映射到指定地址的任意端口 使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。 shell $ docker run -d -p 127.0.0.1::5000 training/webapp python app.py 还可以使用 udp 标记来指定 udp 端口 shell $ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py #### 查看映射端口配置 docker port可用于查看当前映射的端口配置。 shell docker port containerName port > - 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置。) >- -p 标记可以多次使用来绑定多个端口

容器的互联

容器的互联可使用--link参数,但更优的选择是使用自定义Docker网络连接。

新建网络

-d指定Docker网络类型,类型为bridgeoverlay(overlay适用于Swarm)

  docker  network create -d bridge net-test

连接容器

运行一个容器并连接到新建的 net-test 网络

    docker run -it --rm --name busybox1 --network net-test busybox sh
    docker run -it --rm --name busybox2 --network net-test busybox sh

通过ping查看busybox1busybox2容器建立了联系。 在busybox1

   # ping busybox2

busybox2

   # ping busybox1

多个容器之间需要互相连接,使用Docker Compose

DNS

配置所有Docker容器的DNs可通过:

  • etc/resolv.conf
  • 配置etc/docker/daemon.json配置 shell { "dns" : [ "114.114.114.114", "8.8.8.8" ] } 根据docker practice整理而来。