Docker使用手册

作者: 中v中 | 来源:发表于2018-07-19 14:20 被阅读700次


    ocker官网教程(学习一样新东西最快的方法是去看官方文档,讲解的清楚,教程简单,但是包括的面十分的广,只记录自己觉得有用的命令,详细请去官网查看Docker start)

    在docker的学习过程中我也其中也发现一篇很好的教程,简洁明了,我也在这里学到了很多,也摘录总结在了这里,推荐大家去Docker--从入门到实践进行学习。也可以fork那个项目下来进行贡献。如果网速有问题可以docker一个,直接本地访问(教程提供的方法,我只是搬运一下)

    $ docker pull dockerpracticecn/docker_practice$ docker run -it --rm -p4000:80dockerpracticecn/docker_practice

    访问127.0.0.1:4000即可

    手册内容

    Docker的安装(老规矩)

    普通安装方式

    sudo apt-get update

    sudo apt-get install docker.io

    但是上面的下载的版本会比较低,所以建议用下面这种方式

    sudo apt-get install curl

    curl -sSLhttps://get.docker.com/| sh

    下载完毕启动Docker的守护进程

    sudo service docker start

    检查Docker是否安装成功(这是运行了一个容器,后面会有解释)

    sduo docker run hello-world

    如果最终提示Hello from Docker! 如图所示则表明docker安装成功

    安装成功提示

    Docker试水(初级篇)

    10分钟小任务认识Docker

    查看版本号

    docker version

    版本号

    查找镜像 (镜像的全称是/)

    docker search tutorial

    或者可以尝试

    docker search ubuntu

    下载镜像

    docker pull learn/tutorial

    用docker run来创建和运行docker容器(docker可以创建容器并在容器中运行指定的命令)

    docker run learn/tutorial  echo "hello world"

    查看所有容器(加上 -l 可以查看最新创建的容器)

    docker ps

    运行并修改容器(给原容器安装ping)

    docker run learn/tutorial apt-get install -y ping

    通过docker ps -l找出安装过ping包的容器的ID号(-l 是last,找出最新创建的容器)

    docker ps -l

    查看容器

    将安装过ping包的容器提交为新的镜像,这时会返回一个新的ID便是新生成的镜像的ID(意思是把容器打包成镜像,因为平时都是把镜像打开变成容器,这里相当于我们对容器进行了修改,想让更多的人来用,所以我们把我们修改后的容器变成了镜像。镜像易于传播,但是容器不行,)

    docker commit {containId} {new image name}

    docker commit 09c2e9353f01 yugougou/ping

    基于新的镜像创建容器并在容器中执行 pingwww.google.com这条指令(新镜像要使用全名 yugougou/ping)

    docker run yugougou/ping pingwww.google.com

    查询容器信息

    docker ps    查询所有运行的容器

    docker inspect a102  查看单个容器的信息(根据docker ps列出的容器名,选取前三四个字符即可)

    新镜像上传仓库

    docker images  查询本机的镜像列表

    查询结果中有yugoguou/image这个镜像

    查询结果

    所以把镜像推送到Docker官仓(这里有个权限的要求,要求你要在docker hub上有注册过 并输入用户名密码才可以进行上传)

    docker push yugougou/ping

    Docker试水 中级篇

    创建镜像

    首先说明一下 docker中有几个比较重要的概念,『镜像』,『镜像标签』,『容器』,『镜像仓库』,『镜像仓库源』。我简单说下自己的理解。

    镜像就是一个模子,我们可以通过这个模子(镜像)来创建成品(容器),相同的模子(镜像)创建的成品(容器)都是一样的,而且不同的模子(镜像)都是有编号(镜像标签)的。我们可以把我们的模子(镜像)放存放到仓库(镜像仓库)中,这样其他人也可以用。而且呢,仓库(镜像仓库)一般都是放在一个大的厂子(镜像仓库源)里来管理的,以此保证我们的模子(镜像)不会因为太多而管理混乱。

    所以总结一下就是:我们可以在这个工厂(镜像仓库源)的仓库(镜像仓库)中根据标签(镜像标签)拿到我们需要的模子(镜像),来制作生成我们的成品(容器)。

    比如我在生成好自己的镜像并且想要push到镜像仓库的时候,就可以通过地址来看清这几者的关系

    docker push index.alauda.cn/alaudaorg/zpyuregis:syncimagealaudaindex.docker.io      /yugougou/get-started1:zpyutestsyncREGISTORY            REPOSITORY                TAG

    index.docker.io对应镜像源

    /yugougou/get-started1  对应镜像仓库

    :zpyutestsync  对应镜像标签

    这样我就把自己的镜像push到了dockerhub中用户名为yugougou的get-started1的仓库中,而且为了标识清楚这个镜像,我给这个镜像起的一个名字就是zpyutestsync.

    相信通过以上的详细介绍你应该还是没有明白这些概念。。。。,如果真的不明白请再看一遍,如果真的还是不明白,就请动手敲一下代码,接下来我就教大家来创建镜像,启动一个服务,这样应该就会更好的理解了。

    现在我们知道了镜像与容器的关系,知道了容器是由镜像run起来的,那么镜像是怎么来的呢,我们可不可以拥有自己的镜像呢,当然可以,通过dockerfile我们就可以来搭建自己的镜像了,我们先创建一下三个文件:

    Dockerfile

    # Use an official Python runtime as a parent imageFROM python:2.7-slim# Set the working directory to /appWORKDIR /app# Copy the current directory contents into the container at /appADD . /app# Install any needed packages specified in requirements.txtRUN pip install --trusted-host pypi.python.org -r requirements.txt# Make port 80 available to the world outside this containerEXPOSE 80# Define environment variableENV NAME World# Run app.py when the container launchesCMD ["python","app.py"]

    requirements.txt

    Flask

    Redis

    app.py

    fromflaskimportFlaskfromredisimportRedis, RedisErrorimportosimportsocket# Connect to Redisredis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)app = Flask(__name__)@app.route("/")defhello():try:        visits = redis.incr("counter")exceptRedisError:        visits ="cannot connect to Redis, counter disabled"html ="

    Hello {name}!

    "\"Hostname: {hostname}
    "\"Visits: {visits}"returnhtml.format(name=os.getenv("NAME","world"), hostname=socket.gethostname(), visits=visits)if__name__ =="__main__":    app.run(host='0.0.0.0', port=80)

    创建app(注意有个点)

    docker build -t friendlyhello .

    找到新建的镜像

    $ docker imagesREPOSITORY            TAG                IMAGE IDfriendlyhello        latest326387cea39

    跑起来

    docker run -d -p 4000:80 friendlyhello

    访问http://localhost:4000即可,这样你就有了一个flask框架的小的web应用程序了,真是TM的吃了一鲸,对的,就是这么快。好的这个过程我们来慢慢分解一下,当然需要你有一些python开发的基础。

    先说一下这里我们用到的几个文件,Dockerfile、requirements.txt、app.py,其实里面与镜像构建相关的只有Dockerfile,另外两个文件只是用来让这个demo更炫酷一些而已,其实一个Dockerfile就完全可以制作一个镜像了。我们看下Dockerfile里的内容:

    # Use an official Python runtime as a parent imageFROM python:2.7-slim# Set the working directory to /appWORKDIR /app# Copy the current directory contents into the container at /appADD . /app# Install any needed packages specified in requirements.txtRUN pip install --trusted-host pypi.python.org -r requirements.txt# Make port 80 available to the world outside this containerEXPOSE 80# Define environment variableENV NAME World# Run app.py when the container launchesCMD ["python","app.py"]

    其实我想如果你英文稍微好一些,应该大概能明白是什么意思,FROM的作用就是说我要做的这个镜像是基于哪个基础镜像的,这里我们的镜像是基于python:2.7-slim这个基础镜像的,所以我们这个镜像里生来就有python的环境啦。

    看 我没骗你吧

    WORKDIR是说我的工作目录在哪里

    image.png

    (未完待续。。。这几天持续更新重新整理该文章)

    好不容易创建了一个镜像,想分享一下,肿么办

    登录

    docker login

    打标签

    docker tag image username/repository:tag

    举个例子

    docker tag image yugougou/get-started:part2

    这里的于狗狗是你的用户名,get-started是仓库名

    公布镜像

    docker push username/repository:tag

    例如

    docker  push yugougou/get-started:part2

    测试(拉一把 看看能不能跑起来)

    docker run -p 4000:80 username/repository:tag

    例如一个

    docker run -p 4000:80 yugougou/get-started:part2

    如果能成功跑起来,那就没什么问题了

    服务

    要是想要起服务的话,那就要用上编排工具了 docker-compose.yml

    docker-compose.yml(里面有services还有networks)

    version:"3"services:  web:# replace username/repo:tag with your name and image detailsimage: yugougou/get-started:part2    deploy:      replicas: 5      resources:        limits:          cpus:"0.1"memory: 50M      restart_policy:        condition: on-failure    ports:      -"80:80"networks:      - webnetnetworks:  webnet:

    启动第一个负载均衡的app,肯定是少不了要用集群的,这里使用的镜像就是上一节我们制作的镜像。

    docker swarm init

    启动它 给他起一个漂亮的名字

    docker stack deploy -c docker-compose.yml getstartedlab

    看看我们起的服务如何

    docker service ls

    yugougou@yugougoudeMacBook-Pro:~/Desktop$dockerservice lsID                  NAME                MODE                REPLICAS            IMAGE                        PORTS9cinwb60b78b        getstartedlab_web  replicated          10/10              yugougou/get-started:part2  *:80->80/tcp

    看看服务里的任务有哪些吧

    docker service ps getstartedlab_web

    yugougou@yugougoudeMacBook-Pro:~/Desktop$dockerservice ps getstartedlab_webID                  NAME                  IMAGE                        NODE                DESIRED STATE      CURRENT STATE          ERROR              PORTStgbba2qixjoa        getstartedlab_web.1    yugougou/get-started:part2  moby                Running            Running 6 minutes agoeg9oo085u2ud        getstartedlab_web.2    yugougou/get-started:part2  moby                Running            Running 6 minutes agoyjc31x8ac2o0        getstartedlab_web.3    yugougou/get-started:part2  moby                Running            Running 6 minutes agodmoye5s5n09x        getstartedlab_web.4    yugougou/get-started:part2  moby                Running            Running 6 minutes agoq16fo41swnai        getstartedlab_web.5    yugougou/get-started:part2  moby                Running            Running 6 minutes agoidkc65whadin        getstartedlab_web.6    yugougou/get-started:part2  moby                Running            Running 6 minutes agos6k7b8o81m35        getstartedlab_web.7    yugougou/get-started:part2  moby                Running            Running 6 minutes agortod8scwkwt7        getstartedlab_web.8    yugougou/get-started:part2  moby                Running            Running 6 minutes agoz29qubyqa29b        getstartedlab_web.9    yugougou/get-started:part2  moby                Running            Running 6 minutes agopbq7qr4e8jhv        getstartedlab_web.10  yugougou/get-started:part2  moby                Running            Running 6 minutes ago

    只查看端口

    docker ps -q

    哎呀  发现之前的编排文件dockerfile里的副本主机起的不够,肿么办,面对这种状况,分两步,第一步打开冰箱,不是 第一步修改dockerfile,然后重启喽,记得名字不要写错

    yuzhipeng@yuzhipengdeMacBook-Pro:~/Desktop$dockerstack deploy -c docker-compose.yml getstartedlabUpdating service getstartedlab_web (id: 9cinwb60b78bmon03mjakt6mb)

    其实我什么也没有改--__--

    关掉app(关掉之前用docker service ls 看看)

    docker stack rm getstartedlab

    (关掉之前用docker service ls 看看)

    砸了集群

    docker swarm leave --force

    (再用docker service ls看看)

    集群 Swarms

    大家好  我是分隔符

    docker run hello-world

    docker --version

    docker pull --help

    运行jenkins(需要制定端口):

    docker run --name myjenkins -p 8080:8080 index.alauda.cn/alaudaorg/alauda-jenkins

    查看:

    docker ps -a | grep jenkins

    进入docker

    docker exec -ti c3c bash

    编辑docker

    cat /var/run/docker.sock

    docker login index.alauda.cn

    docker-compose up -d

    拉取并运行镜像: docker run --name webserver -d -p 80:80 nginx

    删除容器: docker container rm webserver

    停止容器:docker stop containername

    进入容器修改: docker exec -i -t webserver bash

    今天要总结一下近期来使用学习docker的经验,很早之前就想来摸索一下docker,但是前些日子一直在忙于找工作,没什么时间,但是现在找到的公司做的是基于docker平台开发paas服务的公司,所以借机好好刷一把docker

    体验Docker

    使用docker指令创建 启动几个Docker应用,比如WordPress,gitlab服务

    通过搭建WordPress来试试Docker

    这几个应用下载的话会比较慢 要等几分钟

    sudo docker run --name db --env MYSQL_ROOT_PASSWORD=example -d mariadb

    sudo  docker run --name MyWordPress  --link db:mysql -p 8080:80 -d wordpress

    --name参数创建了两个Docker容器,db和MyWordPress 通过docker ps可以查到名字

    通过ifconfig查看本机的IP地址,在本机地址后加上端口号8080,会有惊喜。简直不能更爽

    这个我在京东云上部署了一下,感觉用起来很快,部署效果非常好,比之前部署项目快的过,真的是几条命令就可以跑起来服务,厉害了访问

    搭建Gitlab服务

    首先启动postgresql

    sudo docker run --name gitlab-postgresql -d --env'DB_NAME=gitlabhq_production'--env'DB_USER=gitlab'--env'DB_PASS=password'sameersbn/postgresql:9.4-12

    然后启动redis

    sudo docker run  --name gitlab-redis -d sameersbn/redis:latest

    最后启动gitlab

    sudo docker run --name gitlab -d --link gitlab-postgresql:postgresql --link gitlab-redis:redisio --publish 10022:22 --publish 10080:80 --env'GITLAB_PORT=10080'--env'GITLAB_SSH_PORT=10022'--env'GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string'sameersbn/gitlab:8.4.4

    后来就可以访问端口10080即可进入gitlab,确实是太好用了,这时候用户名为root,密码是yu123456  连接(如果可用)点击进入

    项目管理系统 Redmine

    要使用saneersbn/redmine的镜像。两条指令

    sudo docker run --name=postgresql-redmine -d --env='DB_NAME=redmine_production'--env='DB_USER=redmine'--env='DB_PASS=password'sameersbn/postgresql:9.4-12 docker run --name=redmine -d --link=postgresql-redmine:postgresql --publish=10083:80 --env='REDMINE_PORT=10083'sameersbn/redmine:3.2.0-4

    Docker常用词

    查看所有的镜像

    docker images

    查看相关进程

    sudo docker ps

    查看版本

    docker version

    ps只是看一些大体容器内容 inspect是看容器的详细内容

    docker ps

    docker inspect gitlab

    docker push michelesr/ping

    docker基础概念与常用命令

    1.仓库、镜像、容器

    2.基本指令

    docker指令操作对象主要针对四个方面:

    1 针对守护进程的系统资源设置和全局信息的获取: docker info, docker deamon

    2 针对Docker仓库的查询,下载 : docker search, docker pull

    3 针对docker镜像的查询,创建与删除: docker images, docker build

    4 针对docker容器的查询,创建,开启,停止: docker ps, docker run

    5 支持赋值,变量解析,嵌套

    docker+命令关键字(command)+一系列参数([arg  ])

    例如

    docker run --name MyWordPress --link db:mysql -p 8080:80 -d wordpress

    基于wordpress镜像创建容器MyWordPress,通过docker ps可以查到名字MyWordPress,使用的镜像是woedpress的容器

    获取帮助

    docker command --help

    Docker容器管理

    容器标识符

    每一个容器创建后都有一个CONTAINER ID作为容器的唯一的标识符,后续对容器的操作都是通过CONTAINER ID来完成,一般docker ps展示前16位,如果查询所有可以使用docker ps --no-trunc

    查询容器状态

    docker ps -a | grep d0131ae38d9d

    停止容器

    docker stop d0131ae38d9d

    运行容器

    docker start d0131ae38d9d

    CONTAINER ID比较难记忆,所以创建容器时会有--name来给容器起一个别名 所以用别名也可以

    查询容器信息(使用-f时可以用golang的模板提取出制定信息)

    docker inspect -f {{.NetworkSettings.IPAddress}} MyWordPress

    查询日志

    docker logs MyWordPress

    查询容器占用的系统资源

    docker stats MyWordPress

    容器内部命令

    单容器

    需求:登入Docker容器执行命令

    方案: Docker提供原生的方式支持登入docker exec

    docker exec + 容器名 + 容器内执行的命令

    查看MyWordPress容器内的进程

    docker exec MyWordPress ps aux

    在容器内连续执行命令 加上 -it 参数即可,相当于以root身份登入,完成后通过 exit 退出

    docker exec -it MyWordPress /bin/bash

    多容器

    Docker理念是‘一个容器一个进程’,如果一个服务由多个进程组成,就创建多个容器组成一个系统

    在同一个主机下,docker run命令提供 ‘--link’建立容器之间的互联,而且他们是有顺序的,比如如果创建B容器的时候需要使用 ‘--link containerA’,那么创建B的时候,那么

    在创建B容器的时候A容器必须已经创建且已经启动

    对于WordPress,数据库容器(db)要先于Apache容器(MyWordPress)启动,所以启动方式应该是

    docker start db

    docker start MyWordPress

    停止WordPress服务,先停止Apache容器(MyWordPress),再停止数据库容器(db),或者同时停止这两个容器

    docker stop db MyWordPress

    Docker compose

    但是如果比较多的容器启动的话就会比较麻烦,本着偷懒的原则,Docker提供了一个容器编排工具--Docker Compose,允许用户用一个模板定义一组相关联的应用容器,会根据配置模板的‘--link’参数对启动的优先级进行排序,只用‘docker-compose up’一条语句即可将一个服务中多个容器依次创建与启动

    安装 Docker compose:(在https://github.com/docker/compose/releases/download这里可以找到随时更新的命令)

    curl -Lhttps://github.com/docker/compose/releases/download/1.18.0-rc2/docker-compose-`uname -s`-`uname -m`-o /usr/local/bin/docker-composechmod +x /usr/local/bin/docker-compose

    使用1:

    首先关掉WordPress的两个容器

    docker stop db MyWordPress

    创建一个文件夹 ~/wordpress,文件夹下创建docker-compose.yml的文件:

    wordpress:

    image: wordpress

    links:

    - db:mysql

    ports:

    - 8080:80

    db:

    image: mariadb

    environment:

    MYSQL_ROOT_PASSWORD: example

    作用:创建了两个容器wordpress跟db,使用image指定了使用的镜像

    创建启动WordPress服务

    cd ~/wordpress &&docker-compose up

    检测

    开另一个命令终端, 输入docker ps查看容器

    这是启动停止就变的简单了,

    启动:

    docker-compose start

    停止:

    docker-compose stop

    删除原来的容器

    查看所有容器(删除与未删除的)

    docker ps -a

    删除(根据名字(NAMES)来删除)

    docker rm MyWordPress db

    硬删的话就用 docker rm -f

    使用2:gitlab改造

    原来的用法

    首先启动postgresqlsudo docker run --name gitlab-postgresql -d --env'DB_NAME=gitlabhq_production'--env'DB_USER=gitlab'--env'DB_PASS=password'sameersbn/postgresql:9.4-12然后启动redissudo docker run  --name gitlab-redis -d sameersbn/redis:latest 最后启动gitlabsudo docker run --name gitlab -d --link gitlab-postgresql:postgresql --link gitlab-redis:redisio --publish 10022:22 --publish 10080:80 --env'GITLAB_PORT=10080'--env'GITLAB_SSH_PORT=10022'--env'GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string'sameersbn/gitlab:8.4.4

    改造结果

    postgresql:  image: sameersbn/postgresql:9.4-12environment:    - DB_USER=gitlab    - DB_PASS=password    - DB_NAME=gitlabhq_productionredis:  image: sameersbn/redis:latestgitlab:  image: sameersbn/gitlab:8.4.4links:    - redis:redisio    - postgresql:postgresql  ports:    -"18008:80"-"18009:22"environment:    - GITLAB_PORT=18008- GITLAB_SSH_PORT=18009- GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alphaumeric-srting

    创建一个项目~/gitlab,然后将上面放在docker-compose.yaml并放在该项目下

    删除旧容器:

    docker rm -f gitlab gitlab-redis gitlab-postgresql

    启动新容器组

    cd ~/gitlab/ && docker-compose up -d

    登录

    http://23.99.104.249:18008/

    root/yu123456

    Docker镜像管理

    docker镜像查看

    docker images -a

    查看镜像分了多少层

    docker history sameersbn/redis

    方式:通过对容器的可写层修改来生成新镜像

    问题:如果底层镜像出了问题,或者达到两个文件系统允许的最多层数(aufs最多支持128层)

    解决方式: dockerfile

    Docker 仓库管理

    作用:镜像的存储,是镜像分发部署的关键

    两种: 官方共有仓库 Docker hub,自己搭建私有仓库

    共有仓库

    上传镜像:

    docker  push ubuntu

    搜索镜像:

    docker search centos

    下载镜像:

    docker pull centos

    私有仓库

    使用docker-registry构建

    方式1:

    从Docker-registry拉取镜像

    docker run -p 5000:5000 registry

    Docker 网络和存储管理

    Docker 网络

    默认情况下使用网桥(bridge)+ NAT的通信模型

    Docker在启动是默认自动创建网桥设备Docker0,同一个host的容器与容器之间可以通过docker0 通信

    容器与外部网络之间通信使用NAT

    Docker数据管理

    Docker数据卷(data volume) 可以持久化数据,用于容器之间共享数据

    docker可以在容器内部创建一个数据卷,但是在删除之后,如果没有其他容器引用该数据卷,对应的Host目录就会被删除。

    不想被删除的话,可以挂载Host的目录到数据卷,作为容器的数据卷(将Host上的/data/volume1挂载容器中的 /volume1可以在Host与容器之间进行数据交换,这时容器中的数据可以写到volume1上,即使容器被删除,数据仍然保留到Host上)

    挂载Host的文件作为数据卷

    主要应用于Host与容器之间共享配置文件,否则每个配置文件一个镜像会造成镜像版本过多,管理不便

    数据卷容器

    备份、恢复和迁移数据卷

    Docker 小点

    容器:

    按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

    数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

    运行镜像

    $ docker run -it --rm \ubuntu:16.04\    bash

    -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。

    --rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。

    ubuntu:16.04:这是指用 ubuntu:16.04 镜像为基础来启动容器。

    bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash。

    列出镜像

    docker image ls

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

    docker system df

    删除镜像

    docker image rm imageid

    docker image rm $(docker image ls -q redis)      //删除大法

    一行码感受一下docker的威力

    $ docker run --name webserver -d -p 80:80 nginx

    Dockerfile

    书写Dockerfile

    touch Dockerfilevi Dockerfile//键入FROM nginxRUN echo'

    Hello, Docker!

    '>/usr/share/nginx/html/index.html

    Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。

    一个比较屌的镜像  (其实run指令里面的命令就是shell命令)

    FROM debian:jessieRUN 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

    所有的命令只有一个目的,就是编译、安装 redis 可执行文件。因此没有必要建立很多层,这只是一层的事情。因此,这里没有使用很多个 RUN 对应不同的命令,而是仅仅使用一个 RUN 指令,并使用 && 将各个所需命令串联起来。

    一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。这是很重要的一步

    Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式

    运行Dockerfile

    $ docker build -t nginx:v3 . //假设该该目录下含有Dockerfile 注意后面有个点,后面会解释

    指定了最终镜像的名称 -t nginx:v3

    need-to-insert-img

    生成的镜像

    查看镜像运行历史

    docker history nginx:v3

    通过镜像运行容器

    docker run --name web2 -d -p 81:80 nginx:v2

    此时通过127.0.0.1:81访问即可访问到docker服务

    点的解释(镜像构建上下文(Context))

    原理

    docker build的工作原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为Docker Remote API,而如docker命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种docker功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。

    使用场景

    当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,经常会需要将一些本地文件复制进镜像,比如通过 COPY 指令、ADD 指令等。而 docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。在这种客户端/服务端的架构中,服务端应该如何获得本地文件,这就是这个上下文的使用场景。

    使用方式

    当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

    如果在 Dockerfile 中这么写:

    > COPY ./package.json /app/

    这并不是要复制执行 docker build 命令所在的目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json,而是复制 上下文(context) 目录下的 package.json。

    应用

    刚才的命令 docker build -t nginx:v3 . 中的这个 .,实际上是在指定上下文的目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。

    Dockerfile命令

    COPY

    格式

    COPY<源路径>...<目标路径>COPY ["<源路径1>",... "<目标路径>"]

    COPY指令将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置。比如:

    COPYpackage.json /usr/src/app/

    <源路径>可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的filepath.Match规则,如:

    COPY hom*/mydir/COPY hom?.txt /mydir/

    <目标路径>可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用WORKDIR指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。

    ADD

    可以自动解压缩  如果是链接也会自动下载,但是功能环境不同,各种功能不能完全预测,所以最佳实践会推荐

    所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。

    CMD 容器启动命令

    Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

    在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如,ubuntu 镜像默认的 CMD 是 /bin/bash,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash。我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release。这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息。

    ENTRYPOINT 入口点(RUN或者其他命令要与参数空一个空格)

    ENTRYPOINT 的格式和 RUN 指令格式一样,分为 exec 格式和 shell 格式。

    ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。

    当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

    ""

    示例

    FROM ubuntu:16.04RUN apt-get update \    && apt-get install -y curl \    && rm -rf /var/lib/apt/lists/*CMD ["curl","-s","http://ip.cn"]

    $ docker run myip当前 IP:61.148.226.66来自:北京市 联通

    嗯,这么看起来好像可以直接把镜像当做命令使用了,不过命令总有参数,如果我们希望加参数呢?比如从上面的 CMD 中可以看到实质的命令是 curl,那么如果我们希望显示 HTTP 头信息,就需要加上 -i 参数。那么我们可以直接加 -i 参数给 docker run myip 么?

    $ docker run myip -idocker:Errorresponsefromdaemon: invalid header field value"oci runtime error: container_linux.go:247: starting container process caused \"exec: \\\"-i\\\": executable file not found in $PATH\"\n".

    显然出了问题,但是entrypoint就不会有这样的问题

    RUN apt-get update \    && apt-get install -y curl \    && rm -rf /var/lib/apt/lists/*ENTRYPOINT ["curl","-s","http://ip.cn"]

    这次我们再来尝试直接使用

    docker run myip -i:$ docker run myip当前 IP:61.148.226.66来自:北京市 联通$ docker run myip -iHTTP/1.1200OKServer: nginx/1.8.0Date: Tue,22Nov201605:12:40GMTContent-Type: text/html; charset=UTF-8Vary: Accept-EncodingX-Powered-By: PHP/5.6.24-1~dotdeb+7.1X-Cache: MISSfromcache-2X-Cache-Lookup: MISSfromcache-2:80X-Cache: MISSfromproxy-2_6Transfer-Encoding: chunkedVia:1.1cache-2:80,1.1proxy-2_6:8006Connection: keep-alive当前 IP:61.148.226.66来自:北京市 联通

    没有问题,最后的-i被entrypoint当做参数加进去了。

    ENV 设置环境变量

    格式有两种:

    ENVENV==...

    这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。对含有空格的值用双引号括起来的办法

    ENV VERSION=1.0 DEBUG=on \    NAME="Happy Feet"

    ARG 构建参数

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

    构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。

    Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。

    VOLUME 定义匿名卷

    格式为:

    VOLUME ["<路径1>", "<路径2>"...]VOLUME<路径>

    之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,后面的章节我们会进一步介绍 Docker 卷的概念。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

    VOLUME /data

    这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置。比如:

    docker run -d -v mydata:/data xxxx

    在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。

    EXPOSE 声明端口

    格式为 EXPOSE <端口1> [<端口2>...]。

    要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。

    WORKDIR 指定工作目录

    格式为 WORKDIR <工作目录路径>。

    使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

    USER 指定当前用户

    格式:USER <用户名>

    USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。WORKDIR 是改变工作目录,USER 则是改变之后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。

    当然,和 WORKDIR 一样,USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

    RUN groupadd -r redis && useradd -r -g redis redisUSER redisRUN ["redis-server"]

    HEALTHCHECK 健康检查

    FROM nginxRUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*HEALTHCHECK --interval=5s --timeout=3s \  CMD curl -fshttp://localhost/||exit1

    这里我们设置了每 5 秒检查一次(这里为了试验所以间隔非常短,实际应该相对较长),如果健康检查命令超过 3 秒没响应就视为失败,并且使用

    curl -fshttp://localhost/|| exit 1

    作为健康检查命令。

    作者:帅气的鱼先森

    链接:https://www.jianshu.com/p/93e7a0cd3e2e

    來源:简书

    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

      本文标题:Docker使用手册

      本文链接:https://www.haomeiwen.com/subject/itrtmftx.html