• Docker虚拟化管理:30分钟教你学会用Docker


    原文地址:https://www.guitu18.com/post/2020/01/20/66.html

    #安装docker
    yum install docker -y  
    #启动docker
    service docker start
    #停止docker
    service docker stop
    #重启docker
    service docker restart
    # 开启Docker开机自启
    systemctl enable docker
    # 关闭Docker开机自启
    systemctl disable docker
    
    # 拉取镜像 mysql
    docker pull mysql:5.7
    #查看本地镜像
    docker images
    #创建容器
    docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
    #查看已创建的容器
    docker ps -a

    三大核心组件

    仓库:仓库是集中存储镜像的地方,我们本地安装Docker之后,需要从仓库中拉取镜像。可以类比于Maven,有公有仓库和私有仓库之分。

    镜像:是一个Linux的文件系统,它里面存放着可以再Linux内核中运行的程序及其数据。

    容器:是镜像创建的运行实例,可以把它理解为一个精简版的Linux系统,里面运行着镜像里的程序。

    为了更好的让你理解这三者的关系,我打一个不恰当但很形象的比方,镜像就相当于你weixin.exe文件,容器相当于你安装好的微信程序,微信程序(容器)需要你的weixin.exe文件(镜像)来安装(创建),那么仓库就相当于应用商店了,你可以从商店下载你要的.exe文件(镜像)。

    微信程序安装完成后你可以选择运行或者关闭,Docker容器一样可以运行和停止,微信程序你可以从系统卸载,Docker容器你同样可以选择删除。

    但有一点不同的地方是,weixin.exe文件安装完成你就可以删除了,它和你的微信程序并没有关系,删掉安装文件不影响你微信程序的运行。但是镜像不同,如果有容器正在使用这个镜像,那么这个镜像是不能删除的(删除时会报Error不让你删)。

    安装Docker

    CentOS安装Docker要求:

    1. 必须是64位操作系统
    2. 内核版本在3.8以上

    你可以通过uname -r查看你的系统内核:

    [root@localhost ~]# uname -r
    3.10.0-1062.18.1.el7.x86_64
    [root@localhost ~]# 

    yum方式安装:

    yum install docker -y

    安装完成你可以通过docker version查看你的docker版本信息:

    [root@localhost ~]# docker version
    Client:
     Version:         1.13.1
     API version:     1.26
     Package version: docker-1.13.1-109.gitcccb291.el7.centos.x86_64
     Go version:      go1.10.3
     Git commit:      cccb291/1.13.1
     Built:           Tue Mar  3 17:21:24 2020
     OS/Arch:         linux/amd64
    
    Server:
     Version:         1.13.1
     API version:     1.26 (minimum version 1.12)
     Package version: docker-1.13.1-109.gitcccb291.el7.centos.x86_64
     Go version:      go1.10.3
     Git commit:      cccb291/1.13.1
     Built:           Tue Mar  3 17:21:24 2020
     OS/Arch:         linux/amd64
     Experimental:    false
     [root@localhost ~]# 

    看到如上的信息说明你的Docker安装成功,你可以用 docker info 命令查看更详细的信息。

    一些常用命令:

    #启动docker
    service docker start
    #停止docker
    service docker stop
    #重启docker
    service docker restart
    
    # 开启Docker开机自启
    systemctl enable docker
    # 关闭Docker开机自启
    systemctl disable docker

    配置镜像加速

    为了更愉快的使用Docker你可能还需要配置镜像加速,可以类比于Maven的私服,使用国内的镜像仓库能让你更快的拉取镜像。

    执行vim /etc/docker/daemon.json,修改为如下配置:

    {
        "registry-mirrors":[
            "https://reg-mirror.qiniu.com/",
            "https://hub-mirror.c.163.com/"
        ]
    }

    重新加载配置及重启Docker服务:

    systemctl daemon-reload
    systemctl restart docker

    执行docker info你可以看到镜像仓库配置已经生效了。

    拉取镜像

    Docker安装和配置都搞定了,现在你要从仓库下载镜像了,这里以 MySQL 5.7 为例:

    # 5.7为版本号,你也可以安装其他版本
    docker pull mysql:5.7

    拉取MySQL5.7镜像

    拉取MySQL5.7镜像

    拉取成功后通过docker images命令查看本地镜像:

    [root@localhost ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    docker.io/mysql     5.7                 f965319e89de        3 hours ago         448 MB
    [root@localhost ~]# 

    创建容器

    有了镜像,你需要用它创建一个容器才能运行,创建并运行MySQL容器:

    docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

    命令参数说明(后面会有更加详细的说明):
    -d:后台运行
    -p:端口映射,前面的为宿主机端口,后面的为容器端口,这里我将宿主机的3306端口指向了容器的3306端口
    --name:为启动的容器命名
    -e:指定容器内的环境变量,这里指配置MySQL的Root用户密码为:123456

    执行成功后会返回容器ID,查看已创建的容器:docker ps -a

    [root@localhost ~]# docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
    8e1cd060075db23c61cb31cecb3a3321df92cf56ea7086476cc21e8709382d19
    [root@localhost ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
    8e1cd060075d        mysql:5.7           "docker-entrypoint..."   3 seconds ago       Up 1 second         0.0.0.0:3306->3306/tcp, 33060/tcp   mysql
    [root@localhost ~]# 

    可以看到刚才创建的MySQL容器已经在运行了,现在你可以通过${IP}:3306连接MySQL数据库了(记得放行端口或者关闭防火墙)。

    挂载目录

    通过上面的步骤,你已经通过Docker运行起你的第一个容器MySQL了,而且你也能通过宿主机的端口连接到容器中的MySQL。但这样做还不是很安全,关于这个我们要先简单了解一下容器和宿主机之间的关系。

    容器内和宿主机的文件系统是独立的(虽然整个容器也是以文件的形式存放在宿主机的某个目录上的),包括他们之间的网络,也是独立的。刚才运行的MySQL容器有一个 -p 3306:3306 的参数,这个参数就是映射宿主机和容器之间的端口的,你也可以配置成比如 -p 1234:3306 ,这样你通过访问宿主机的1234端口就能访问到容器的3306端口。

    那么再回到文件系统,容器本身也是一个精简版的Linux系统,只不过他运行在宿主机上依赖于宿主机的硬件。容器内部也是有着一套独立的文件系统的,且随着容器的删除,所有存在于容器内的所有文件都将被清除。刚才我们创建的那个MySQL容器,只要我们删除容器,数据库里的所有数据都将清除,这显然不是我们想看到的。

    Docker的run命令提供了一个-v的参数,允许我们容器内部目录挂载为宿主机的本地目录,这样容器内的程序在操作这个目录时,其实操作的是宿主机的目录。那么我们可以把程序运行的关键数据挂载到宿主机上的目录,比如MySQL的数据库文件,程序运行的日志文件等等。这样一来当我们在删除容器时,因为这些目录是存在于宿主机的,所以不会随着容器一起删除,从而实现了容器数据的持久化。

    还是以刚才的MySQL容器为例,我们先删掉刚才的容器:

    # mysql为容器名称,也可以是容器ID,通过 docker ps -a 查看容器信息
    docker stop mysql
    docker rm mysql

    接着用下面的命令创建并运行MySQL容器,增加了一个 -v 参数:

    # 在宿主机创建挂载目录
    mkdir -p /usr/local/mysql/logs
    mkdir -p /usr/local/mysql/data
    # 创建并运行容器
    docker run -p 3306:3306 --name mysql 
    -v /usr/local/mysql/logs:/var/log/mysql 
    -v /usr/local/mysql/data:/var/lib/mysql 
    -e MYSQL_ROOT_PASSWORD=123456 
    -d mysql:5.7

    -v /usr/local/mysql/data:/var/lib/mysql

    表示将宿主机的 /usr/local/mysql/data 目录挂载到容器内的 /var/lib/mysql 目录,那么容器内的MySQL程序操作的数据实际上是写入了宿主机的 /usr/local/mysql/data 目录了,其他两项同理。

    这里挂载的三个目录分别为数据库运行的配置、日志和数据,也是MySQL程序最重要的数据,即便这个容器删除了,只要这些数据还在,我们就能通过重新创建容器恢复全部数据。

    而且这样挂载以后,我们无需进入容器,直接在宿主机操作这几个目录里的文件就能同步体现到容器内部,比如修改一些配置,导出数据之类的,不用进入容器直接在宿主机操作即可。

    用以上命令运行容器之后,在你的宿主机的/usr/local/mysql/data 目录就能看到MySQL运行生成的数据库文件了:

    容器内MySQL运行后生成的数据文件,已经挂载到宿主机上了

    容器内MySQL运行后生成的数据文件,已经挂载到宿主机上了

    Docker的数据卷挂载(我习惯称之为挂载目录)功能非常重要,我们运行的任何程序都有需要持久化的数据,如果这些数据直接放在容器内部是非常不安全的。而且挂载目录还可以实现直接在宿主机操作容器内的数据,也能做到容器间的数据共享,用Docker一定要养成挂载重要数据到宿主机的习惯。

    错误排查

    上面这个命令是直接后台运行容器的,如果需要调试可以把 -d 参数修改为 -it 参数以在前台运行,在某些情况下你很可能会遇到类似于下面这些错误(可以通过前台运行查看到):

    chown: changing ownership of '/var/lib/mysql/': Permission denied
    # 或者
    mysqld: Can't create/write to file '/var/lib/mysql/is_writable' (Errcode: 13 - Permission denied)

    如果出现上述问题,那么你需要关闭SELINUX,方法如下:

    1. 临时关闭:setenforce 0
    2. 永久关闭:vim /etc/selinux/config,修改 SELINUX 的值为 disabled 然后重启机器即可,看图:

    修改SELINUX配置

    修改SELINUX配置

    再次运行容器就能看到成功提示了。

    常用命令

    通过上面的示例基本已经知道了Docker是怎样工作的,下面是一些基本命令,包括最常用的目录挂载功能等命令说明:

    docker version|info
    # 显示Docker信息,常用于查看Docker版本或检测Docker是否正确安装。
    
    docker images
    # 列出机器上的镜像(images)及信息:REPOSITORY、TAG、IMAGE ID、CREATED、SIZE。
    # IMAGE ID列其实是缩写,要显示完整则带上--no-trunc选项。
    # -a 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层)
    # -no-trunc 显示完整的镜像信息
    # -q 静默模式,只显示镜像ID
    
    docker search tomcat
    # 在docker index中搜索image,搜索的范围是官方镜像和所有个人公共镜像。NAME列的 / 后面是仓库的名字。
    
    docker pull tomcat
    # 从docker registry server 中下拉image或repository。
    # 语法:docker pull [OPTIONS] NAME[:TAG|@DIGEST]
    # -a 拉取所有 tagged 镜像
    # --disable-content-trust 忽略镜像的校验,默认开启
    # 上面的命令没有指定参数,在docker v1.2版本及以前,会下载官方镜像的tomcat仓库里的所有镜像
    # 而从v.13开始只会下载tag为latest的镜像,也可以明确指定具体的镜像
    # 如:docker pull tomcat:8,后面的8为tomcat版本tag。
    
    docker run -d --name tomcat -p 8081:8080 tomcat:8
    # 启动容器,语法为:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
    # -d 后台运行容器,并返回容器ID,不使用-d我们会看到tomcat启动日志,此时Ctrl+C容器会停止运行。
    # -e 指定容器内的环境变量
    # -name 指定容器的名称,如果不指定docker会帮我们取一个名字。
    # -p 端口映射,宿主机端口:容器端口,上面我们就将宿主机的8081映射到容器的8080端口
    #     此时我们访问宿主机的ip:8081就能访问容器内的tomcat了。
    # -i 以交互模式运行容器,通常与 -t 同时使用。
    # -t 为容器重新分配一个伪输入终端,通常与 -i 同时使用
    # -v 目录挂载,本地目录:容器目录
    
    docker ps
    # 查看容器的信息,默认显示当前正在运行中的容器
    # -a 查看所有容器
    # -l 显示最新启动的一个容器(包括已停止的)
    
    docker start|stop|restart CONTAINER_ID
    # 启动/停止/重启容器,需要用到容器ID,可以使用docker ps -a 查看所有容器的ID。
    
    docker attach CONTAINER_ID|NAME
    # 进入容器,后面跟容器ID或者NANE,可以使用docker ps -a 查看所有容器的ID。
    # 可以认为这是一个过时的命令,更多的docker用户会考虑使用docker exec来实现相同的功能
    # 但是出于docker官方并没有删除这个命令,我们还是有必要学习一下的。
    # 进入容器后输入exit命令可以退出,同时容器停止运行,如若想退出但不停止容器,可以用快捷键Ctrl+P+Q退出。
    
    docker exec -i -t CONTAINER_ID|NAME /bin/bash
    # 进入容器,推荐使用这种方式。
    # 语法:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
    # -i 以交互模式运行容器,通常与 -t 同时使用。
    # -t 为容器重新分配一个伪输入终端,通常与 -i 同时使用
    # 示例:docker exec -it mycentos /bin/sh /root/start.sh
    # 上面这条命令表示在容器 mycentos 中以交互模式执行容器内 /root/start.sh 脚本
    
    docker rm CONTAINER_ID|NAME
    # 删除一个或多少容器,如:docker rm $(docker ps -a -q),为删除所有停止的容器
    # -l 移除容器间的网络连接,而非容器本身
    # -v 删除与容器关联的卷
    # -f 通过SIGKILL信号强制删除一个运行中的容器
    
    docker rmi CONTAINER_ID|NAME
    # 删除本地一个或多少镜像
    # -f 强制删除;
    # --no-prune 不移除该镜像的过程镜像,默认移除;
    
    docker build
    # 使用 Dockerfile 创建镜像,语法:docker build [OPTIONS] PATH | URL | -
    # -f 指定要使用的Dockerfile路径
    #  -t,--tag 指定镜像的名字及标签:name:tag或者name,可以在一次构建中为一个镜像设置多个标签

    Dockerfile

    Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

    初学者一开始可不必关注Dockerfile,待你熟悉Docker的整个体系结构及其运行方式后,再回头看这个就会一目了然了。

    FROM
    # 指定基础镜像,必须为第一个命令
        FROM <image>
        FROM <image>:<tag>
        FROM <image>@<digest>
    # 示例
        FROM docker.io/centos:latest
    MAINTAINER
    # 维护者信息
        MAINTAINER <name>
    # 示例
        MAINTAINER guitu "xianjian-mail@qq.com"
    RUN
    # 用于在镜像容器中执行命令,其有以下两种命令执行方式
    #shell执行
        RUN <command>
    #exec执行
        RUN ["executable", "param1", "param2"]
    #示例
        RUN apk update
        RUN ["executable", "param1", "param2"]
        RUN ["/etc/execfile", "arg1", "arg1"]
    # RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。
    # 如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
    ADD 
    # 将当前目录下的文件复制到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
        ADD <src>... <dest>
        ADD ["<src>",... "<dest>"]
        # 第二中形式用于支持包含空格的路径
    # 示例
        ADD hom* /mydir/          # 添加所有以"hom"开头的文件
        ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
        ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
        ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/
    # <src>可以是Dockerfile所在目录的一个相对路径,也可以是一个URL,还可以是一个tar文件(会自动解压为目录)
    # 如果文件或目录不与Dockerfile在同一目录会提示 no such file or directory
    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"]
    # CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
    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> <key>=<value> <key>=<value> ...
    # 示例
        LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
    # 使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。
    # 推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
    ENV
    # 设置环境变量
        ENV <key> <value>  
        # <key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
        ENV <key>=<value> ...  
        # 可以设置多个变量,每个变量为一个"<key>=<value>"的键值对
        # 如果<key>中包含空格,可以使用来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
    # 示例
        ENV JAVA_HOME /docker/jdk
    VOLUME
    # 用于指定持久化目录
        VOLUME ["/path/to/dir"]
    # 示例
        VOLUME ["/data"]
        VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
    # 一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
        # 卷可以容器间共享和重用
        # 容器并不一定要和其它容器共享卷
        # 修改卷后会立即生效
        # 对卷的修改不会对镜像产生影响
        # 卷会一直存在,直到没有任何容器在使用它
    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/local/bin/python-build --dir /app/src
    # 当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发

    构建镜像

    了解了上面的命令之后,我们可以尝试着创建我的第一个自制镜像了,以下是我的Dockerfile示例:

    #使用的基础镜像
    FROM docker.io/centos:latest
    #作者信息
    MAINTAINER guitu "xianjian-mail@qq.com"
    #安装SVN
    RUN yum install -y subversion
    #添加JAVA环境,下方的文件请换成你Dockerfile目录下的文件,压缩包在构建镜像时会自动解压
    ADD jdk-8u231-linux-x64.tar.gz /docker/
    ADD apache-tomcat-8.0.53.tar.gz /docker/
    #添加环境变量
    ENV JAVA_HOME /docker/jdk1.8.0_231
    ENV TOMCAT_HOME /docker/apache-tomcat-8.0.53
    ENV PATH $PATH:$JAVA_HOME/bin:$TOMCAT_HOME/bin
    #指定工作目录
    WORKDIR /docker/apache-tomcat-8.0.53
    #暴露8080端口
    EXPOSE 8080
    #启动时运行tomcat
    CMD ["bin/startup.sh && tail -f logs/catalina.out"]

    通过Dockerfile创建镜像:

    docker build -t mytomcat8:v0.1 .

    通过Dockerfile文件构建镜像完成。

  • 相关阅读:
    VBS基础篇
    AcWing249 蒲公英(分块)
    CF1338B Edge Weight Assignment(思维+dfs)
    CF785E Anton and Permutation(分块)
    UCF Local Programming Contest 2015(Practice)D题
    AcWing851 spfa求最短路
    CF479E Riding in a Lift (dp)
    AcWing267 莫基亚(CDQ分治)
    P4093 [HEOI2016/TJOI2016]序列 (CDQ分治)
    2019ICPC南昌区域赛C题 And and Pair(数位dp)
  • 原文地址:https://www.cnblogs.com/zhuawang/p/13546899.html
Copyright © 2020-2023  润新知