这几天学了一下docker的相关知识,记录一下

安装

官网有教程

卸载旧版本

1
2
3
4
5
6
7
8
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

安装新版本

需要centos7版本以上的

安装一些必要的系统工具:

1
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

添加软件源信息:

1
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装 Docker-ce:

1
sudo yum install -y docker-ce

启动 Docker 后台服务:

1
2
sudo systemctl start docker
sudo systemctl enable docker

Docker镜像加速

在拉取Docker镜像时如果未指明镜像地址则默认从docker-hub上拉取,国内访问docker-hub的速度较慢,所以需要将docker源更改为国内的源。
配置/etc/docker/daemon.json即可,我使用的是阿里云的源:

1
2
3
4
5
6
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://w76qpozk.mirror.aliyuncs.com"]
}
EOF

保存配置后需要重启服务:

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

相关命令

  • 查看容器

    1
    2
    3
    4
    # 查看运行中的容器
    docker ps
    # 查看所有容器
    docker ps -a
  • 删除镜像

    1
    docker rm 容器id
  • 查看镜像

    1
    docker images
  • 删除镜像

    1
    docker rmi 镜像id
  • 进入容器内部

    1
    docker exec -it 容器id /bin/bash
  • 构建Dockerfile

    1
    docker build -t runoob/ubuntu:v1 . 

    Dockerfile

    原文

    Dockerfile的基本结构

    Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,”#” 为 Dockerfile 中的注释。

文件说明

  • FROM:指定基础镜像,必须为第一个命令

    指定基础镜像,必须为第一个命令

    1
    2
    3
    4
    5
    6
    7
    #格式:
    FROM <image>
    FROM <image>:<tag>
    FROM <image>@<digest>
    #示例:  
    FROM mysql:5.6
    # 注:tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
  • MAINTAINER: 维护者信息

    1
    2
    3
    4
    #格式:
    MAINTAINER name<email address>
    #示例:
    MAINTAINER DLYT<xxx@163.com>
  • RUN:构建镜像时执行的命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
    #shell执行
    #格式:
    RUN <command>
    #exec执行
    #格式:
    RUN ["executable", "param1", "param2"]
    #示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
    #注RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
  • ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #格式:
    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"] #用于支持包含空格的路径
    #示例:
    # 添加所有以"hom"开头的文件
    ADD hom* /mydir/
    # ? 替代一个单字符,例如:"home.txt"
    ADD hom?.txt /mydir/
    # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test relativeDir/
    # 添加 "test" 到 /absoluteDir/
    ADD test /absoluteDir/
  • COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

  • CMD:构建容器后调用,也就是在容器启动时才进行调用

    1
    2
    3
    4
    5
    6
    7
    8
    # 格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
    # 示例:
    CMD echo "This is a test." | wc -
    CMD ["/usr/bin/wc","--help"]
    # 注:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
  • ENTRYPOINT:配置容器,使其可执行化。配合CMD可省去”application”,只使用参数

    1
    2
    3
    4
    5
    6
    7
    8
    #格式:
    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
    ENTRYPOINT command param1 param2 (shell内部命令)
    #示例:
    FROM ubuntu
    ENTRYPOINT ["top", "-b"]
    CMD ["-c"]
    #注:ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
  • LABEL:用于为镜像添加元数据

    1
    2
    3
    4
    5
    #格式:
    LABEL <key>=<value> <key>=<value> <key>=<value> ...
    #示例:
      LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
    #注:使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
  • ENV:设置环境变量

    1
    2
    3
    4
    5
    6
    7
    #格式:
    ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
    ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
    # 示例:
    ENV myName John Doe
    ENV myDog Rex The Dog
    ENV myCat=fluffy
  • EXPOSE:指定于外界交互的端口

    1
    2
    3
    4
    5
    6
    7
    #格式:
    EXPOSE <port> [<port>...]
    #示例:
    EXPOSE 80 443
    EXPOSE 8080
    EXPOSE 11211/tcp 11211/udp
    #注:EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
  • VOLUME:用于指定持久化目录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #格式:
    VOLUME ["/path/to/dir"]
    #示例:
    VOLUME ["/data"]
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
    #注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
    # 1 卷可以容器间共享和重用
    # 2 容器并不一定要和其它容器共享卷
    # 3 修改卷后会立即生效
    # 4 对卷的修改不会对镜像产生影响
    # 5 卷会一直存在,直到没有任何容器在使用它
  • WORKDIR:工作目录,类似于cd命令

    1
    2
    3
    4
    5
    6
    7
    #格式:
    WORKDIR /path/to/workdir
    #示例:
    WORKDIR /a (这时工作目录为/a)
    WORKDIR b (这时工作目录为/a/b)
    WORKDIR c (这时工作目录为/a/b/c)
    #注:通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工

    构建镜像

    docker build [OPTIONS]上下文路径|URL

  • [OPTIONS]:通常指令包括-t,用来指定image的名字。-f指定Dockfile的上下文路径。

  • 上下文路径|URL:上下文路径,如果只有一个小圆点 “.” 代表当前目录。

示例 构建一个名字为 webtest 的镜像

1
docker bulid -t  webtest .  

docker-compose

基本格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
version: '2'
services:
web:
image: dockercloud/hello-world
ports:
- "8080:8080"
networks:
- front-tier
- back-tier
volumes:
- my_volumes:/usr/local/bin

redis:
image: redis
links:
- web
networks:
- back-tier

lb:
image: dockercloud/haproxy
ports:
- "80:80"
links:
- web
networks:
- front-tier
- back-tier
volumes: # 宿主机与容器内目录共享
- /var/run/docker.sock:/var/run/docker.sock
volumes: # 声明上面创建的卷名
my_volumes:
networks:
front-tier:
driver: bridge
back-tier:
driver: bridge

可以看到一份标准配置文件应该包含 versionservicesnetworks 三大部分,其中最关键的就是 servicesnetworks 两个部分,下面我们来看其书写规则。

services

  • image

    1
    2
    3
    services:
    web:
    image: hello-world

    services 标签下的第二级标签是 web,这个名字是用户自己自定义,它就是服务名称。
    image 则是指定服务的镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。

  • container_name

    相当于docker build 中的 –name

  • depends_on

    在使用 Compose 时,最大的好处就是少打启动命令,但是一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。
    例如在没启动数据库容器的时候启动了应用容器,这时候应用容器会因为找不到数据库而退出,为了避免这种情况我们需要加入一个标签,就是 depends_on,这个标签解决了容器的依赖、启动先后的问题。
    例如下面容器会先启动 redis 和 db 两个服务,最后才启动 web 服务:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    version: '2'
    services:
    web:
    build: .
    depends_on:
    - db
    - redis
    redis:
    image: redis
    db:
    image: postgres
  • 还记得上面的depends_on吧,那个标签解决的是启动顺序问题,这个标签解决的是容器连接问题,与Docker client的–link一样效果,会连接到其它服务中的容器。
    格式如下:

    1
    2
    3
    4
    links:
    - db
    - db:database
    - redis

    使用的别名将会自动在服务容器中的/etc/hosts里创建。例如:

    1
    2
    3
    172.12.2.186  db
    172.12.2.186 database
    172.12.2.187 redis

    相应的环境变量也将被创建。

  • environment

    这个标签的作用是设置镜像变量,它可以保存变量到镜像里面,也就是说启动的容器也会包含这些变量设置,这是与 arg 最大的不同。
    一般 arg 标签的变量仅用在构建过程中。而 environment 和 Dockerfile 中的 ENV 指令一样会把变量一直保存在镜像、容器中,类似 docker run -e 的效果。

1
2
3
4
5
6
7
8
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW='true'
- SESSION_SECRET=
  • ports

    映射端口的标签。
    使用HOST:CONTAINER格式或者只是指定容器的端口,宿主机会随机映射端口。

    1
    2
    3
    4
    5
    ports:
    - "3000"
    - "8000:8000"
    - "49100:22"
    - "127.0.0.1:8001:8001"

    注意:当使用HOST:CONTAINER格式来映射端口时,如果你使用的容器端口小于60你可能会得到错误得结果,因为YAML将会解析xx:yy这种数字格式为60进制。所以建议采用字符串格式。

  • networks

    加入指定网络,同一网络可以相互通讯,格式如下:

    1
    2
    3
    4
    5
    services:
    some-service:
    networks:
    - some-network
    - other-network