• Docker 的镜像和容器(系统学习Docker03)


    写在前面

    最为基础重要的两大概念:镜像和容器
    Docker 底层技术支持:

    Namespaces : 做隔离pid/net/ipc/mnt/uts
    Control Groups : 做资源限制
    Union file systems: Container 和 image 的分层


    镜像Image

    Image的获取方式(1):
    (1)Build from Dockerfile
    Dockerfile 有自己的语法
    docker pull hello-world
    docker image ls
    发现只有1.85k,但是它任然是一个 Base Image
    docker run hello-world

    DIY一个:
    	mkdir hello-world
    	cd hello-world
    		vim hello.c
    		#include<stdio.h>
    		int main(){
    			printf("hello world!")
    		}
    	yum -y install gcc glibc-static
    	gcc -o hello hello.c
    	./hello 
    	
    # 创建 Dockerfile  ,构成一个Base Image
    	vim Dockerfile
    	FROM scratch
    	ADD hello / 
    	CMD ["/hello"]
    	
    # 构建build:docker build -t liuge36/hello-world .
    	
    #查看分层:docker history 796a6f9eb6a1
    	
    	docker run liuge36/hello-world  就变成了一个container
    

    Image的获取方式(2):
    (2)Pull from registry
    仓库中拉取image,默认的仓库是docekr hub
    docker push 推的话就需要注册docker hub
    docker pull ubuntu:14.04
    docker images

    docker image rm imgaeID
    docker rmi imageID

    √ √ √ √ √ √ √ 小技巧:普通用户不加sudo 来执行docker的命令 √ √ √ √ √ √ √ √
    sudo groupadd docker // 创建一个组
    sudo gpasswd -a vagrant docker // 将用户添加到docker用户组里面
    sudo service docker restart
    重新登录 vagrant ssh

    ----------------------3.4 容器container--------
    container 通过Image 创建(copy)
    Image 本身是只读的
    在Image layer 之上建立一个container layer(便成为 可读写)
    类比面向对象中的内容就是: 类(image) 和 实例(container)
    Image 负责app的存储和分发,Container 负责运行app

    打印出本地正在运行的容器:

    docker container ls
    docker ps

    查看所有的容器,把常驻内存并没有运行的 的那些搞出来

    docker container ls -a
    docker ps -a

    交互式的运行

    docker run -it centos
    yum install -y vim
    exit 退出之后就不会再运行了

    退出的容器,删除容器

    docker container rm ID
    docker rm ID

    快速清理掉所有 container

    清理掉 所有常驻内存并没有运行的容器:
    01.列出
    docker container ls -aq // -q只列出ID
    docker container ls -a |awk {‘print$1’}
    02.清理掉
    docekr rm $(docker container ls -aq )
    03.验证
    docker ps -a

    #更加复杂的情况,想把退出的删除掉 ,运行的保留
    01 列出exited 状态的container
    docker container ls -f “status=exited”
    02 删除掉
    docker rm $(docker container ls -f “status=exited” -q)

    ---------------------3.5 构建自己的镜像--------------------------
    01 # 把container 重新commit一个new image
    基于已有的image ,在创建成为一个container 之后,
    做了一些改变(安装了软件),想把这个新的改变打成新的image
    docker container commit
    docker commit
    demo:
    docker run -it centos // 基于Base image 交互式起一个container
    yum -y install vim // 本来没有,安装一个
    exit
    docker container ls -a
    docker commit ID/name dockerID/centos-vim
    docker images

    docker history ImageID(原来的)
    docker history ImageID(新的)

    02 #Build an image from a Dockerfile
    docker image build
    docker build

    mkdir docker-centos-vim
    cd docker-centos-vim
    vim Dockerfile
    FROM centos // 选定 Base image (只读的?怎么run!其实是先基于临时的)
    RUN yum install -y vim // 在Base image 上运行安装命令

    开始构建

    docker build -t liuge36docker/centos-vim-new .

    03 # 详解Dockerfile
    介绍各个关键字
    —FROM—
    FROM scratch # 制作base image // 不依赖其他的image,原创一个
    FROM centos # 使用base image // 基于已有的image 基础上

    from最佳实践:尽量使用官方的image作为base image ,为了安全!

    —LABEL—
    定义image的metadata,像代码写注释一样
    LABEL maintainer=“liuge36@163.com 作者”
    LABEL version=“1.0”
    LABEL description=“这里是image的描述信息”

    label最佳实践:Metadata必不可少!

    ----RUN—
    运行一些命令,比如安装软件
    RUN yum update && yum install -y vim
    python-dev #反斜线换行

    RUN apt-get update && apt-get install -y perl
    pwgen --no-install-recommends && rm -rf
    /var/lib/apt/lists/* # 注意清理cache

    RUN /bin/bash -c ‘source $HOME/.bashrc;echo $HOME’

    RUN最佳实践:为了美观,复杂的RUN 使用反斜线换行
    避免无用分层,合并多条命令为一行,即一层。&&

    ----WORKDIR—
    指定工作目录,就像cd /opt/spark/ 这种操作

    WORKDIR /test #如果没有会自动创建test目录
    WORDDIR demo # 进入到/test/demo
    RUN pwd # 输出结果应该是/test/demo

    WORKDIR最佳实践:尽量使用绝对路径,尽量不使用RUN cd 这种方式

    ----ADD 和 COPY ------
    用于添加本地的文件到docker image内部

    ADD : 可以添加和解压缩

    ADD springboot.jar / # 把本地的文件添加到image里面
    ADD test.tar.gz / #添加到根目录并解压缩

    WORDDIR /root
    ADD springboot.jar test/ # /root/test/springboot.jar

    WORDDIR /root
    COPY springboot.jar test/

    ADD 和 COPY 最佳实践:大部分情况:COPY 优于ADD,但是ADD有解压的功能
    添加远程的文件/目录请使用curl或wget下载

    ----ENV------
    设定环境变量

    ENV MYSQL_VERSION 5.6 # 设定常量,后面直接用
    RUN apt-get install -y mysql-server= “${MYSQL_VERSION}”
    && rm -rf /var/lib/apt/lists/* # 引用常量,清理cache

    ENV 最佳实践:尽量使用ENV,可以增加可维护性,就像maven使用version一样

    –VOLUME 和 EXPOSE—
    存储和网络

    —CMD 和 ENTERPOINT ----
    RUN : 执行命令并创建新的Image Layer(新的镜像层)
    CMD: 设置容器启动后 默认执行 的命令和参数
    ENTERPOINT: 设置容器 启动时 运行的命令

    拓展:shell 格式 和 Exex格式

    Shell 格式:
    RUN apt-get install -y vim
    CMD echo “hello docker~~”
    ENTERPOINT echo “hello docker~~2”

    Exec 格式:
    RUN [“apt-get”,“install”,"-y",“vim”]
    CMD ["/bin/echo",“hello docekr~~”]
    ENTERPOINT ["/bin/echo",“hello docekr~~2”]

    小案例:
    Dockerfile1
    FROM centos
    ENV name DcoerLiuge # 设定一个常量
    ENTERPOINT echo “hello $name”

    // docker build -t liuge36docker/centos-enteypoint-shell .
    // docker run liuge36docker/centos-enteypoint-shell
    hello DcoerLiuge // 打印出来,OK。没有问题

    Dockerfile2
    FROM centos
    ENV name DockerLiuge2
    ENTERPOINT ["/bin/echo",“hello $name”]

    // docker build -t liuge36docker/centos-enteypoint-exec .
    // docker run liuge36docker/centos-enteypoint-exec
    hello name//name // 无法打印,不能识别name 的值。并不是shell
    修改如下:
    Dockerfile3
    FROM centos
    ENV name DockerLiuge2
    ENTERPOINT ["/bin/bash","-c",“echo hello $name”] // 指明是shell

    你去build ,run 是可以打印 hello DockerLiuge2 的。

    –CMD–

    • 容器启动时,默认执行的命令
    • 如果是 docker run 指定了其他命令,CMD命令会被忽略
    • 如果定义了多个CMD ,只有最后一个会执行

    例如:Dockerfile
    FROM centos
    ENV name DcoerLiuge
    CMD echo “hello $name”

    根据上面这个Dockerfile构建一个image之后,
    docker run [image] // 输出结果是:hello DcoerLiuge
    docker run -it [image] /bin/bash // 定义的CMD就会被忽略,不会被打印

    –ENTERPOINT–

    • 让容器以应用程序或者服务的形式运行
    • 永不会被忽略,一定会执行

    最佳实践:写一个shell脚本作为 entrypoint
    COPY docker-entrypoint.sh /usr/local/bin/ # 拷贝一个shell脚本进去image
    ENTERPOINT [“docker-entrypoint.sh”] # 作为一个启动脚本

    EXPOSE 27017
    CMD [“mongod”]

    最佳实践:参考官方的Dockerfile 进行学习和修改
    https://github.com/docker-library

    比如 mysql5.7 Dockerfile:
    https://github.com/docker-library/mysql/blob/master/5.7/Dockerfile

    ------------3.6 # Dockerfile 实战一 ------------
    mkdir flask-demo
    cd flask-demo
    vim app.py

    from flask import Flask
    app = Flask(name)
    @app.route(’/’)
    def hello():
    return “Hello Flask~~”
    if name == ‘name’:
    app.run()

    直接运行:
    pip install -y flask
    python app.py

    目的:把这个python app 打包成一个image,再运行起来
    开始吧:
    分析,运行这个app,需要python 和flask的环境依赖

    第一步:准备app源代码
    mkdir flask-hello-world
    cd flask-demo-world
    vim app.py

    from flask import Flask
    app = Flask(name)
    @app.route(’/’)
    def hello():
    return “Hello Flask~~”
    if name == ‘name’:
    app.run()

    第二步:编写Dockerfile

    我们写Dockerfile就可以基于python Base image
    vim Dockerfile
    FROM python:2.7 # Base Image
    LABEL maintainer=“liuge36liuge36@163.com
    RUN pip install -i https://pypi.douban.com/simple flask
    COPY app.py /app/
    WORDDIR /app # 设定工作目录

    EXPOSE 5000 # 暴露5000端口
    CMD ["python","app.py"]
    

    :wq

    第三步:根据Dockerfile Build Image
    docker build -t liuge36docker/flask-hello-world .

    出错:? 可以docker exec -it [image] /bin/bash

    第四步:docker run -d liuge36docker/flask-hello-world

    ------------3.7 # image 的分发 ------------------
    即:pull push 操作
    基于dockerhub 。类似github
    可以把自己build的image ,push上去

    push 的前提 :要注册dockerhub

    要想push,得先登录
    [root@localhost ~]# docker login
    Login with your Docker ID to push and pull images from Docker Hub. If you don’t have a Docker ID, head over to https://hub.docker.com to create one.
    Username: liuge36docker
    Password:
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store

    Login Succeeded
    [root@localhost ~]#

    登录成功之后,就可以push了
    #先删除带hello的container
    docker rm $(docker ps -a |grep hello | awk {‘print$1’})

    删除image 重新构建

    docker rm [image]
    docker build -t liuge36docker/hello-world .

    开始push

    [root@localhost hello-world]# docker push liuge36docker/hello-world:latest
    The push refers to repository [docker.io/liuge36docker/hello-world]
    d669ced3dff5: Pushed
    latest: digest: sha256:fc659b21569c4a05751438f9cf8910ad8a1267263843cdd835ac798a09a8c6b1 size: 525
    [root@localhost hello-world]#

    刷新自己的dockerhub https://hub.docker.com/repositories

    别人就可以拉取你的image了
    [root@localhost hello-world]# docker rmi 2d73a16744c8
    Untagged: liuge36docker/hello-world:latest
    Untagged: liuge36docker/hello-world@sha256:fc659b21569c4a05751438f9cf8910ad8a1267263843cdd835ac798a09a8c6b1
    Deleted: sha256:2d73a16744c88b95b064512543dea778aa051d931efa999d66a8bfd6e3838c24
    Deleted: sha256:873c2d5ea1784b7ebcad04ee444d5b9f1c02b1d241018f5e644dab183c3b069c
    Deleted: sha256:d669ced3dff508cec5444c056a30b34e2f98d75bc0cf9c062a31e0f25799ba08
    [root@localhost hello-world]# docker images |grep hello
    hello-world latest fce289e99eb9 13 months ago 1.84kB
    [root@localhost hello-world]# docker pull liuge36docker/hello-world:latest
    latest: Pulling from liuge36docker/hello-world
    908ba8edad07: Pull complete
    Digest: sha256:fc659b21569c4a05751438f9cf8910ad8a1267263843cdd835ac798a09a8c6b1
    Status: Downloaded newer image for liuge36docker/hello-world:latest
    docker.io/liuge36docker/hello-world:latest
    [root@localhost hello-world]# docker images |grep hello
    liuge36docker/hello-world latest 2d73a16744c8 5 minutes ago 8.44kB
    hello-world latest fce289e99eb9 13 months ago 1.84kB
    [root@localhost hello-world]#

    √ √ √ √ √ √ √ 小技巧 : 将自己的github与docekrhub进行关联 √ √ √ √ √ √ √

    √ √ √ √ √ √ √ 小技巧 : 根据官方提供的registry image搭建本地的registry,供公司或个人创建私有的 √ √ √ √ √ √ √

    云服务器本机启动一台registry
    $ docker run -d -p 5000:5000 --restart always --name registry registry:2
    telnet 120.27.243.X 5000
    
    本地往云服务器上面push
    01 先build
    docker build -t 120.27.243.X:5000/hello-world .
    02 创建信任文件
    vim /etc/docker/daemon.json 
    # 添加
    { "insecure-registries":["120.27.243.X:5000"] }
    03 vim /lib/systemd/system/docker.service 
    #添加一行
    EnvironmentFile=-/etc/docker/daemon.json
    //ExecReload=/bin/kill -s HUP $MAINPID
    
    04 systemctl restart docker
    
    05 docker push 120.27.243.X:5000/hello-world
    
    06 验证:120.27.243.X:5000/v2/_catalog
    

    ------------3.8 # 容器container的操作 ------------------
    命令一:exec
    01 bash进入运行中的容器:-it 交互式的进入
    docker exec -it 容器ID/名称 /bin/bash
    pwd
    ps -ef |grep python
    exit

    02 python进入
    docker exec -it 容器ID/名称 python

    print “Hello Docker”

    03 打印容器的IP地址
    docker exec -it 容器ID/名称 ip a
    命令二:stop start rm
    docker stop 容器ID/名称
    docker rm $(docker ps -aq) # 删除已退出的容器

    指定名字
    docker run -d --name=flask-demo liuge36docker/flask-hello-world

    命令三:inspect
    打印container详细信息
    docker inspect 容器ID/名称

    命令四:logs
    运行日志
    docker logs 容器ID/名称

    ------------3.9 # Dockerfile 实战二 ------------
    CMD 结合 ENTERPOINT 一起使用

    工具:命令行程序
    build 一个linux的命令行工具

    stress linux压力测试的工具
    docker run -it ubuntu /bin/bash
    /# apt-get update && apt-get install -y stress
    which stress
    stress --help

    vm worker.默认占用256M内存
    stress --vm 1
    stress --vm 1 --verbose
    创建一个worker
    分配占用256M
    释放进程
    不断往复~~~

    如何把stress打包成一个docker image
    mkdir ubuntu-stress
    cd ubuntu-stress
    vim Dockerfile
    FROM ubuntu
    RUN apt-get update && apt-get install -y stress

    ENTERPOINT ["/usr/bin/stress"]
    CMD []
    

    Build Image

    docekr build -t liuge36/ubuntu-stress .

    Run

    docker run -it liuge36/ubuntu-stress
    加上参数:
    docker run -it liuge36/ubuntu-stress --vm 1 --verbose

    常驻内存的程序
    命令行的工具

    ------------3.10 # 容器资源限制 ------------
    CPU memory
    在容器技术之前的虚拟化技术,虚拟机是可以做资源的 分配限定的

    docker run --help
    -m --memory

    docker images

    docker run --memory=200M liuge36/ubuntu-stress --vm 1 --verbose

    –memory=200M 200+200swap一共400m

    docker run --memory=200M liuge36/ubuntu-stress --vm 1 --verbose --vm-bytes 500M

    -c --cpu-shares 相对权重,不是个数

    docker run --cpu-shares=10 --name=test1 liuge36/ubuntu-stress --cpu 1
    docker run --cpu-shares=5 --name=test2 liuge36/ubuntu-stress --cpu 1


    有什么问题,欢迎留言讨论~~

    更多文章:系统学习Docker 不迷路:https://blog.csdn.net/liuge36/category_7651616.html

  • 相关阅读:
    linux下ssh端口的修改和登录
    linux找回密码
    XAMPP命令之LAMPP
    VirtualBox 复制vdi文件和修改vdi的uuid
    探讨PHP页面跳转几种实现技巧
    CSS盒模型和margin重叠
    8--数组旋转
    9--斐波那契数列
    7--动态规划
    6--树的遍历
  • 原文地址:https://www.cnblogs.com/liuge36/p/12614678.html
Copyright © 2020-2023  润新知