docker学习笔记

208 阅读9分钟

image 文件

Docker 把应用程序及其依赖,打包在 image 文件里面。 只有通过这个文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。

image 是二进制文件。实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设置而生成。举例来说,你可以在 Ubuntu 的 image 基础上,往里面加入 Apache 服务器,形成你的 image

image 文件是通用的,一台机器的 image 文件拷贝到另一台机器,照样可以使用。一般来说,为了节省时间,我们应该尽量使用别人制作好的 image 文件,而不是自己制作。即使要定制,也应该基于别人的 image 文件进行加工,而不是从零开始制作

docker image pull library/hello-world

上面代码中,docker image pull是抓取 image 文件的命令。library/hello-world是 image 文件在仓库里面的位置,其中library是 image 文件所在的组,hello-world是 image 文件的名字

由于 Docker 官方提供的 image 文件,都放在library组里面,所以它的是默认组,可以省略。因此,上面的命令可以写成下面这样

docker image pull hello-world
// 列出本机的所有 image 文件。
docker image ls 或 docker images
// 删除 image 文件  (在容器中运行的镜像无法被删除,需先删除容器再删除镜像)
docker image rm [imageName] 或 docker rmi [imageName/IMAGE ID]

镜像的导入导出(不规范)

// 将本地镜像导出
docker save -o 导出的路径 镜像id
// 加载本地的镜像文件
docker load -i 镜像文件

修改镜像名称 docker tag 镜像id 新镜像名称:版本

现在,运行这个 image 文件

docker container run hello-world

如果运行成功,你会在屏幕上读到下面的输出

​
$ docker container run hello-world
​
Hello from Docker!
This message shows that your installation appears to be working correctly.
​
... ...
​

输出这段提示以后,hello world就会停止运行,容器自动终止。

有些容器不会自动终止,因为提供的是服务。比如,安装运行 Ubuntu 的 image,就可以在命令行体验 Ubuntu 系统

docker container run -it ubuntu bash
# 对于那些不会自动终止的容器,必须使用docker container kill 命令手动终止
docker container kill [containID]

容器文件

image 文件生成的容器实例,本身也是一个文件,称为容器文件。 也就是说,一旦容器生成,就会同时存在两个文件: image 文件和容器文件。而且关闭容器并不会删除容器文件,只是容器停止运行而已

# 列出本机正在运行的容器
docker container ls# 列出本机所有容器,包括终止运行的容器
docker container ls --all

上面命令的输出结果之中,包括容器的 ID。很多地方都需要提供这个 ID,比如上一节终止容器运行的docker container kill命令。

终止运行的容器文件,依然会占据硬盘空间,可以使用docker container rm命令删除

docker container rm [containerID]

运行上面的命令之后,再使用docker container ls --all命令,就会发现被删除的容器文件已经消失了

容器的管理

  • 运行容器

    简单操作 docker run 镜像的标识镜像名称[:tag]

  • 常用参数

    docker run -d -p 宿主机端口:容器端口 --name 容器名称 镜像的表示镜像名称[:tag]

    • -d:代表后台运行容器
    • -p 宿主机端口:容器端口: 为了映射当前linux的端口和容器的端口
    • --name 容器名称: 指定容器的名称
  • 查看正在运行的容器

    docker ps [-qa]

    • -a:查看全部的容器,包括没有运行的
    • -q:只查看容器的标识
  • 查看容器日志

    docker logs -f 容器id

    • -f:可以滚动查看日志的最后几行
  • 进入到容器内部

    docker exec -it 容器id bash

  • 删除容器(删除前,需要先停止容器运行)

    // 启动容器
    docker start 容器ID
    // 停止指定的容器
    docker stop 容器ID
    // 停止全部容器
    docker stop $(docker ps -qa)
    // 重启容器
    docker restart 容器ID
    // 删除指定容器
    docker rm 容器ID
    // 删除全部容器
    docker rm $(docker ps -qa)
    

[常见的应用场景]

1.快速部署 2.隔离应用 3.提高开发效率 4.版本控制

docker数据卷

将宿主机的一个目录映射到容器的一个目录中,可以在宿主机中操作目录中的内容,容器内部映射的问价也会一起改变

1.创建数据卷

docker volume create 数据卷名称

创建数据卷之后,默认会存放在一个目录下 /var/lib/docker/volumes/数据卷名称/_data

2.查看数据卷的详细信息

docker volume inspect 数据卷名称

  1. 查看全部数据卷

    docker volume ls

  2. 删除数据卷

    docker volume rm 数据卷名称

  3. 应用数据卷

    当你映射数据卷时,如果数据卷不存在Docker会帮你自动创建,会将容器内部自带的文件存储在默认的存放路径中

    docker run -v 数据卷名称:容器内部的路径 镜像ID
    // 直接指定一个路径作为数据卷的存放位置。这个路径下是空的 (推荐)
    docker run -v 路径:容器内部的路径 镜像ID
    

docker命令

docker --version  //查看版本
docker ps //查看正在运行的容器状态 -a 参数来查看所有的已经运行的容器(无论是否停止)
docker run //创建一个新的容器并运行一个命令
docker exec // 进入容器里面
-it // 提供交互式终端
-d //让镜像容器在后台去持续运行
--name //指定容器的名称
-p // 容器内部端口映射到主机的端口
-v // 挂载宿主机的文件目录到镜像里面去
-e //设置环境变量

例子

// 运行容器
docker run -it -d --name test ubuntu
// 进入容器
docker exec -it test /bin/bash
// 把本机的Downloads文件映射到ubuntu的home文件下
docker run -v ~/Downloads/:home -itd --name test1 ubuntu

Dockerfile

一般,Dockerfile 共包括四部分:

  • 基础镜像信息

  • 维护者信息

  • 镜像操作指令

  • 容器启动时执行指令

    Dockerfile示例:

    # nginx Dockerfiel
    # version 1.0# Base images 基础镜像
    FROM centos
    ​
    # MAINTAINER 维护者信息
    MAINTAINER fall
    ​
    # ENV 设置环境变量
    ENV PATH /usr/local/nginx/sbin:$PATH# ADD 文件放在当前目录下,拷过去自动解压
    ADD nginx-1.8.0.tar.gz /usr/local/
    ADD epel-release-latest-7.noarch.rpm /usr/local/ # 企业linux扩展包# RUN 执行一下命令
    RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
    RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
    RUN useradd -s /sbin/nologin -M www
    ​
    # WORKDIR 设置工作目录
    WORKDIR /uer/local/nginx-1.8.0
    ​
    RUN ./configuer --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install
    RUN echo "daemo off;" >> /etc/nginx.conf
    ​
    # EXPOSE 映射端口暴露
    EXPOSE 80
    ​
    # CMD 运行以下命令
    CMD ["nginx"]
    
    FROM node:10
    LABEL maintainer=atiedan666666@163.com
    # 创建 app 目录
    WORKDIR /app
    ​
    # 把 package.jsonpackage-lock.json(npm@5+) 或 yarn.lock 复制到工作目录(相对路径)
    COPY ["package.json","*.lock","./"]
    ​
    # 打包 app 源码
    # 特别注意:要指定工作目录中的文件名
    COPY src ./src
    ​
    # 使用.dockerignore文件,上面两个COPY合并成一个
    # COPY . .
    ​
    # 使用Yarn安装 app 依赖
    # 如果你需要构建生产环境下的代码,请使用:
    # --prod参数
    RUN yarn --prod --registry=https://registry.npm.taobao.org
    ​
    # 对外暴露端口 -p 4000:3000
    EXPONSE 3000CMD ["node", "src/index.js"]
    
    • FROM:指定基础镜像,必须为第一个命令;
    #格式:
        FROM <image>
        FROM <image>:<tag>
        FROM <image>@<digest>
    #示例: FROM mysql:5.6
    # tag或digest是可选的,如果不使用这2个值,会使用latest版本的基础版本
    
    • MAINTAINER:维护者信息
    #格式:
        MAINTAINER <name>
    #示例:
        MAINTAINER jack li
        MAINTAINER jackgmail.com
        MAINTAINER jack li <jackgmail.com>
    
    • RUN:构建镜像时执行的命令
     # shell执行
        #格式:RUN <command>
     # exec执行
        #格式:RUN ["executable", "param1", "params2"]
     # 示例:
        RUN ["executable", "param1", "param2"]
        RUN apk update
        RUn ["/ect/exedile", "arg1", "arg2"]
    ​
     # RUN命令创建的中间镜像会被缓存,并在下次构件中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
    
    • ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网路资源,类似wget
    # 格式
        ADD <src>... <dest>
        ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
    # 示例:
        ADD home* /mydir/ # 添加所有以“home“开头的文件
        ADD hom?.txt /mydir/ # ?替代一个字符,如home.txt
        ADD test relativeDir/ # 添加”test“到”WORKDIR /relativeDir/
        ADD test /absoluteDir/ # 添加“test”到/adsoluteDir/
    
    • COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
    • CMD:构建容器后调用,也就是在容器启动时才进行调用
    # 格式:
        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"]
    
    • ENTRYPOINT: 配置容器,使其可执行化。配合CMD可省区"application",只使用参数
     # 格式:
        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: 用于为镜像添加元数据
    # 格式:
        LABEL <key>=<value> <ke>=<value> <key>=<value>
    # 示例:
        LABEL version="1.0" description="web server" by="lionL"
    
    • ENV:设置环境变量
     # 格式:
        ENV <key> <value> # <key>之后所有内容均会被视为其value的组成部分,故一次只能设置一个变量
        ENV <key>=<value>... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如过<key>中包含空格使用\进行转义,也可通过""来进行标示;另外,反斜线也可以用来续行
    ​
     # 示例:
        ENV myName Jhon Doe
        ENV myDog Rex The Dog
        ENV myCat=tom
    
    • EXPOSE:指定与外界交互的端口
    # 格式:
        EXPOSE <port> [<port>....]
    # 示例:
        EXPOSE 80 443
        EXPOSE 8080 EXPOSE 11211/tcp 11211/udp
    # 注:EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过该-p参数来发布EXPOSE导出的所有端口
    
    • VOLUME: 用于指定持久化目录
     # 格式:
        VOLUME ["/path/to/dir"]
     # 示例:
        VOLUME ["/data"]
        VOLUME ["/var/www", "/var/log/apache1", "var/log/apache2"]
    ​
     # 注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件类型,并具有以下功能:
        1 卷可以容器间共享和重用
        2 容器并不一定要和其他容器共享卷
        3 修改卷后会立即生效
        4 对卷的修改不会对镜像产生影响
        5 卷会一直存在,直到没有任何容器在使用它
    
    • WORKDIR:工作目录,类似于cd命令
     # 格式:
        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参数覆盖构建时所设置的工作目录
    
    • USER:指定运行容器时的用户名或UID,后续的RUN也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或者两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
    # 格式:
        USER user
        USER user:group
        USER uid
        USER uid:gid
        USER user:gid
        USER uid:group
    # 示例:
        USER www
    # 注:使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker
    run运行容器时,可以通过-u参数来覆盖所指定的用户
    
    • ARG: 用于指定传递给构建运行时的变量
    # 格式:
        ARG <name>[=<default value>]
    # 示例:
        ARG site
        ARG build_user=www
    
    • ONBUILD: 用于设置镜像触发器
     # 格式:
        ONBUILD [INSTRUCTION]
     # 示例:
        ONBUILD ADD . /app/src
        ONBUILD RUN /usr/loacl/bin/python-build --dir /app/src
    ​
     # 注:当构建的镜像被用作其他镜像的基础镜像,该镜像中的触发器将会被触发
    

    本地生成node应用

    • 一个简单的Koa应用:
    const Koa = require('koa');
    const app = new Koa();
    ​
    // response
    app.use(ctx => {
      ctx.body = 'Hello Koa!!';
    });
    ​
    app.listen(3000);
    

    打包镜像 使用docker build打包:

    docker build -t ${your_name}/${image_name}:${tag} .
    

    docker build命令用于从Dockerfile构建镜像,可以在增加-f指向文件系统中任意位置的Dockerfile

    docker build -f /path/to/a/Dockerfile

    这里的your_name代表的是远程仓库中的用户名,或者仓库地址; image_name为镜像名称,tag是给镜像打的标签,用于版本控制。. 代表当前目录例如:

    docker build -t zyq/node-demo:1.0 .
    # docker build -t 镜像名称[:tag]
    

    使用镜像

    docker run -d --name nodedemo -p 4000:3000 zyq/node-demo:1.0
    

Docker-compose

通过 Docker-Compose 用户可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题

Compose 中有两个重要的概念:

  • 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例
  • 项目(project): 由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义

Docker Compose 是 Docker 的独立产品,因此需要安装 Docker 之后在单独安装 Docker Compose

#下载
sudo curl -L https://github.com/docker/compose/releases/download/1.20.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
#安装
chmod +x /usr/local/bin/docker-compose
#查看版本
docker-compose --version

使用

docker-compose.yml改写:

version: '3.8'
services:
    mysql:                                   # 服务的名称
      restart: always                         # 代表只要Docker启动,那么这个容器就跟着一起启动
      image: daocloud.io/library/mysql:5.7.4  # 指定镜像路径                        # 
      container_name: test_mysql               # 指定容器名称
      ports:
        - 8001:3306                       # 指定端口映射
      environment:
        MYSQL_ROOT_PASSWORD: 123456            # 指定mysql的root用户登录密码
        TZ: Asia/Shanghai                     # 指定时区
       volumes:
         - /opt/docker_mysql-tomcat/mysql_data:/var/lib/mysql # 映射数据卷
    tomcat:
      restart: always
      image: daocloud.io/library/tomcat:8.5.15-jre8
      container_name: tomcat
      ports:
        - 8080:8080
      environment:
        TZ: Asiz/Shanghai
      volumes:
        - home/tomcat_webapps:/usr/loacl/tomcat/webaps
        - home/tomcat_logs:/usr/local/tomcat/logs
       

在此文件的当前目录下,使用docker-compose up -d来执行

关闭并删除容器docker-compose down

查看docker-compose维护的容器 docker-compose pse

查看日志 docker-compose logs -f

生命周期管理:

  • 创建:run/up
  • 启动/停止/删除/重启:start/stop/rm/restart
  • 捡视/日志: logs/ps

docker-compose结合Dockerfile使用

version: '3.8'
services:
    web-demo:
      restart: always
      build:                    # 构建自定义镜像
        context: ../             # 指定Dockerfile文件所在路径
        dockerfile: Dockerfile    # 指定Dockerfile文件名称
      image: demo:1.0
      container_name: demo
      ports:
        8081:8080
      environment:
        TZ: Asia/Shanghai

Dockerfile

FROM daocloud.io/library/tomcat:8.5.15-jre8
COPY demo.war /usr/local/tomcat/webapps

应用

搭建本地mongo + mongo-express服务

# docker-compose.mongo.yml配置文件
version: '3.1'
services:
    mongo:
        image:mongo
        restart: always
        environment:
            MONGO_INITDB_ROOT_USERNAME: root
            MONGO_INTIDB_ROOT_PASSWORD: 13456
            
    mongo-express:
        image: mongo-express
        restart: always
        ports:
         - 8081:8081
        environment:
            ME_CONFIG_MONGODB_ADMINUSERNAME: root
            ME_CONFIG_MONGODB_ADMINPASSWARD: 123456

执行:

# 执行 docker-compose.mongo.yml  如果不加 docker-compose -f 默认执行 docker-compose.mongo.yml
docker-compose -f docer-compose.mongo.yml up -d