Docker使用手册

作者: mace3170 | 来源:发表于2017-12-13 23:24 被阅读729次

docker官网教程(学习一样新东西最快的方法是去看官方文档,讲解的清楚,教程简单,但是包括的面十分的广,只记录自己觉得有用的命令,详细请去官网查看Docker start),其中也发现一篇很好的教程,简洁明了,我也在这里学到了很多,也摘录总结在了这里,推荐大家去Docker--从入门到实践进行学习。也可以fork那个项目下来进行贡献。如果网速有问题可以docker一个,直接本地访问(教程提供的方法,我只是搬运一下)

$ docker pull dockerpracticecn/docker_practice

$ docker run -it --rm -p 4000:80 dockerpracticecn/docker_practice

访问127.0.0.1:4000即可

  • 初识Docker

了解docker的祖师级别的语句,如同代码里的hello-world

docker run hello-world

查看版本

docker --version

  • 容器
    需要了解dockerfile,docekrfile其实很好懂,容器是由镜像创建的,镜像呢,现在来说是dockerfile创建的。以下三个文件是

Dockerfile

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.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 images

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea39

跑起来

docker run -d -p 4000:80 friendlyhello

访问http://localhost:4000即可


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

登录

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 details
    image: yugougou/get-started:part2
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "80:80"
    networks:
      - webnet
networks:
  webnet:

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

docker swarm init

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

docker stack deploy -c docker-compose.yml getstartedlab

看看我们起的服务如何

docker service ls


yugougou@yugougoudeMacBook-Pro:~/Desktop $docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                        PORTS
9cinwb60b78b        getstartedlab_web   replicated          10/10               yugougou/get-started:part2   *:80->80/tcp

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

docker service ps getstartedlab_web

yugougou@yugougoudeMacBook-Pro:~/Desktop $docker service ps getstartedlab_web
ID                  NAME                   IMAGE                        NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
tgbba2qixjoa        getstartedlab_web.1    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
eg9oo085u2ud        getstartedlab_web.2    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
yjc31x8ac2o0        getstartedlab_web.3    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
dmoye5s5n09x        getstartedlab_web.4    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
q16fo41swnai        getstartedlab_web.5    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
idkc65whadin        getstartedlab_web.6    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
s6k7b8o81m35        getstartedlab_web.7    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
rtod8scwkwt7        getstartedlab_web.8    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
z29qubyqa29b        getstartedlab_web.9    yugougou/get-started:part2   moby                Running             Running 6 minutes ago
pbq7qr4e8jhv        getstartedlab_web.10   yugougou/get-started:part2   moby                Running             Running 6 minutes ago

只查看端口

docker ps -q

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

yuzhipeng@yuzhipengdeMacBook-Pro:~/Desktop $docker stack deploy -c docker-compose.yml getstartedlab
Updating 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的安装

sudo apt-get update

安装 这是用比较新的方法 也可以用

sudo apt-get install docker.io

但是这个下载的版本会比较低 不建议这样下载

sudo apt-get install curl

 curl -sSL  https://get.docker.com/  | sh

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

sudo service docker start

检查Docker是否安装成功

sduo docker run hello-world

如果提示Hello from Docker!

当然是里面有提示,并不是一开始的提示就是这个,说明安装成功了提示(Ubnable to find image 'hello-world lateset' locally)

如果不想总是输入sudo 可以输入以下命令解决

sudo usermod -aG docker yuzhipeng


体验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


10分钟小任务认识Docker

版本号

docker version

查找镜像 (镜像的全称是 <username>/<repository>)

docker search tutorial

下载镜像

docker pull learn/tutorial

docker ps -l

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

docker run learn/tutorial echo "hello world"

修改容器(安装ping)

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

通过docker ps -l找出安装过ping包的容器的ID号,

docker ps -l

然后将容器提交为新的镜像,这时会返回一个新的ID便是新生成的镜像的ID

docker commit 09c2e9353f01 learn/ping

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

docker run learn/ping ping www.google.com

查询容器信息

docker ps 查询所有运行的容器

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

新镜像上传仓库

docker images 查询本机的镜像列表

查询结果中有

REPOSITORY                                                                      TAG                 IMAGE ID            CREATED             SIZE
learn/ping                                                                      latest              714c84471b9f        11 minutes ago      139MB

所以把镜像推送到Docker官仓

docker push learn/ping


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 -L https://github.com/docker/compose/releases/download/1.18.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

使用1:

  1. 首先关掉WordPress的两个容器

docker stop db MyWordPress

  1. 创建一个文件夹 ~/wordpress,文件夹下创建docker-compose.yml的文件:
    wordpress:
    image: wordpress
    links:
    - db:mysql
    ports:
    - 8080:80
    db:
    image: mariadb
    environment:
    MYSQL_ROOT_PASSWORD: example
    作用:创建了两个容器wordpress跟db,使用image指定了使用的镜像

  2. 创建启动WordPress服务

cd ~/wordpress &&docker-compose up

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

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

启动:

docker-compose start

停止:

docker-compose stop

  1. 删除原来的容器

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

docker ps -a

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

docker rm MyWordPress db

硬删的话就用 docker rm -f

使用2: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

改造结果

postgresql:
  image: sameersbn/postgresql:9.4-12
  environment:
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production

redis:
  image: sameersbn/redis:latest

gitlab:
  image: sameersbn/gitlab:8.4.4
  links:
    - 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) 可以持久化数据,用于容器之间共享数据
  1. docker可以在容器内部创建一个数据卷,但是在删除之后,如果没有其他容器引用该数据卷,对应的Host目录就会被删除。
  2. 不想被删除的话,可以挂载Host的目录到数据卷,作为容器的数据卷(将Host上的/data/volume1挂载容器中的 /volume1可以在Host与容器之间进行数据交换,这时容器中的数据可以写到volume1上,即使容器被删除,数据仍然保留到Host上)
  3. 挂载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 Dockerfile
vi Dockerfile
//键入
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

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

FROM debian:jessie

RUN 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


生成的镜像

查看镜像运行历史

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

COPY package.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 指令,换句话说实际执行时,将变为:

<ENTRYPOINT> "<CMD>"

示例

FROM ubuntu:16.04
RUN 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 -i
docker: Error response from daemon: 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 -i
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 22 Nov 2016 05:12:40 GMT
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.24-1~dotdeb+7.1
X-Cache: MISS from cache-2
X-Cache-Lookup: MISS from cache-2:80
X-Cache: MISS from proxy-2_6
Transfer-Encoding: chunked
Via: 1.1 cache-2:80, 1.1 proxy-2_6:8006
Connection: keep-alive

当前 IP:61.148.226.66 来自:北京市 联通

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

  • ENV 设置环境变量
    格式有两种:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 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 redis
USER redis
RUN [ "redis-server" ]
  • HEALTHCHECK 健康检查
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -fs http://localhost/ || exit 1

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

curl -fs http://localhost/ || exit 1

作为健康检查命令。

相关文章

  • Module-Docker使用手册

    LinuxDocker 使用手册 [toc] Docker 介绍 Docker 的应用场景 Web 应用的自动化打...

  • DOCKER命令手册

    DOCKER使用手册 1.创建启动容器 -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器...

  • 包的管理-软件列表

    gem使用手册npm使用手册yarn使用手册pip-使用手册maven-使用手册composer-使用手册 cho...

  • Docker使用手册

    ocker官网教程(学习一样新东西最快的方法是去看官方文档,讲解的清楚,教程简单,但是包括的面十分的广,只记录自己...

  • Docker使用手册

    docker官网教程(学习一样新东西最快的方法是去看官方文档,讲解的清楚,教程简单,但是包括的面十分的广,只记录自...

  • Docker使用手册——前言

    Docker 简介 Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。...

  • Docker极简使用手册

    Docker是什么?可以简单的理解为,Docker是在主机上为应用程序提供一个沙箱运行环境的一套工具,而这个“沙箱...

  • PostMan使用手册

    Postman 使用手册系列教程: Postman软件安装Postman使用手册1——导入导出和发送请求查看响应P...

  • YOU:身体使用手册Ⅱ 罗伊森

    YOU:身体使用手册Ⅱ 罗伊森.pdf: 内容简介······ “自己是自己最好的医生”是《YOU:身体使用手册(...

  • blender3.0使用手册及快捷键大全

    blender在线使用手册[http://dd.ma/6VKc0W6o] blender及网页使用手册下载地址 b...

网友评论

本文标题:Docker使用手册

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