92e8b27955aa4c1a193b6fa86e880dd5.png

docker基本命令

是一个开源的应用容器引擎;是一个轻量级容器技术;

docker主机(Host):安装了Docker程序的机器(Docker直接安装在操作系统之上);

docker客户端(Client):连接docker主机进行操作;

docker仓库(Registry):用来保存各种打包好的软件镜像;

docker镜像(Images):软件打包好的镜像;放在docker仓库中;

docker容器(Container):镜像启动后的实例称为一个容器;容器是独立运行的一个或一组应用

docker引擎

  1. docker daemon process docker后台服务直接执行dockerd启动后台服务
  2. rest接口 程序可以通过rest接口来访问后台服务
  3. docker cil 交互式命令行界面 docker开头的所有命令都与docker cil交互

镜像操作

知乎不支持表格所以只能这样

f30306aa4565456d913e131e2df44af7.png

容器操作

运行容器

docker run [选项] 镜像名
选项
-d 后台运行
-it 提供容器交互
--name 设置容器名
--cpus 设置cpu个数
--env 设置环境变量
--mount type=bind,source=/root/target,target=/app或者--mount type=tmpfs,destination=/app 
--volume <host>:<container>:[rw|ro]挂载一个磁盘卷 例如 --volume /home/hyzhou/docker:/data:rw
--restart 设置重启策略on-failure,no,always
--privileged 使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。privileged启动的容器,可以看到很多host上的设备,并且可以执行mount。甚至允许你在docker容器中启动docker容器。

volume bind-mount tmpfs-mount

Volumes和Bind mounts模式使我们能够在宿主机和容器间共享文件从而我们能够将数据持久化到宿主机上,以避免写入容器存储层带来的容器停止后数据的丢失的问题。

tmpfs mounts,顾名思义,是一种非持久化的数据存储。它仅仅将数据保存在宿主机的内存中,一旦容器停止运行,tmpfs mounts会被移除,从而造成数据丢失。

一个简单区分volumesbind mountstmpfs mounts不同点的方法是:思考数据在宿主机上是如何存在的。

  • Volumes由Docker管理,存储在宿主机的某个地方(在linux上是/var/lib/docker/volumes/)。非Docker应用程序不能改动这一位置的数据。Volumes是Docker最好的数据持久化方法。
  • Bind mounts的数据可以存放在宿主机的任何地方。数据甚至可以是重要的系统文件或目录。非Docker应用程序可以改变这些数据。
  • tmpfs mounts的数据只存储在宿主机的内存中,不会写入到宿主机的文件系统。

详细区别https://michaelyou.github.io/2017/09/17/Docker%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86-Volume%EF%BC%8C-bind-mount%E5%92%8Ctmpfs-mount/

f1f6a1993ca0c8b76583492f2ce966c6.png

Dockerfile

DockerFile

# 使用官方提供的 Python 开发镜像作为基础镜像 
FROM python:2.7-slim 
# 将工作目录切换为 /app 
WORKDIR /app 
# 将当前目录下的所有内容复制到 /app 下 
ADD . /app
# 使用 pip 命令安装这个应用所需要的依赖 
RUN pip install --trusted-host pypi.python.org -r requirements.txt 
# 允许外界访问容器的 80 端口 
EXPOSE 80 
# 设置环境变量 
ENV NAME World 
# 设置容器进程为:python app.py,即:这个 Python 应用的启动命令 
CMD ["python", "app.py"]

其中,RUN 原语就是在容器里执行 shell 命令的意思。

而 WORKDIR,意思是在这一句之后,Dockerfile 后面的操作都以这一句指定的 /app 目录作为当前目录。

Dockerfile中的ENTRYPOINT指令和CMD指令都可以设置容器启动时要执行的命令,但用途是有略微不同的。

cmd : cmd给出的是一个容器的默认的可执行体。也就是容器启动以后,默认的执行的命令。重点就是这个“默认”。意味着,如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么,就会使用cmd指定的默认的执行命令执行。可以被docker run 语句覆盖。

entrypoint : 是真正的容器启动以后要执行命令。不会被docker run 语句覆盖。

所以,到了最后的 CMD,意思是 Dockerfile 指定 python app.py 为这个容器的进程。这里,app.py 的实际路径是 /app/app.py。所以,CMD [“python”, “app.py”] 等价于 "docker run python app.py"。另外,在使用 Dockerfile 时,你可能还会看到一个叫作 ENTRYPOINT 的原语。实际上,它和CMD 都是 Docker 容器进程启动所必需的参数,完整执行格式是:“ENTRYPOINT CMD”。

但是,默认情况下,Docker 会为你提供一个隐含的 ENTRYPOINT,即:/bin/sh -c。所以,在不指定 ENTRYPOINT 时,比如在我们这个例子里,实际上运行在容器里的完整进程是:/bin/sh -c “python app.py”,即 CMD 的内容就是 ENTRYPOINT 的参数。

备注:基于以上原因,我们后面会统一称 Docker 容器的启动进程为ENTRYPOINT,而不是 CMD。

需要注意的是,Dockerfile 里的原语并不都是指对容器内部的操作。就比如ADD,它指的是把当前目录(即 Dockerfile 所在的目录)里的文件,复制到指定容器内的目录当中。

读懂这个 Dockerfile 之后,我再把上述内容,保存到当前目录里一个叫“Dockerfile”的文件中:

$ ls
Dockerfile app.py requirements.txt

接下来,我就可以让 Docker 制作这个镜像了,在当前目录执行:

docker build -t helloworld .

其中,-t 的作用是给这个镜像加一个 Tag,即:起一个好听的名字。docker build 会自动加载

当前目录下的 Dockerfile 文件,然后按照顺序,执行文件中的原语。而这个过程,实际上可以

等同于 Docker 使用基础镜像启动了一个容器,然后在容器中依次执行 Dockerfile 中的原语。

需要注意的是,Dockerfile 中的每个原语执行后,都会生成一个对应的镜像层。即使原语本身

并没有明显地修改文件的操作(比如,ENV 原语),它对应的层也会存在。只不过在外界看来,这个层是空的。

其他字段

ARG 参数名 = 参数值

构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。

docker compose

用于定义和运行多个Docker应用程序的工具

#启动相关服务
docker-compose up -d
#编译服务
docker-compose build .
#停止相关服务
docker-compose down
#删除服务
docker-compose rm 服务名
#运行单个服务(容器)
docker-compose run 服务名

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境。
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

quick start

1、准备

创建一个测试目录:

$ mkdir composetest
$ cd composetest

在测试目录中创建一个名为 app.py 的文件,并复制粘贴以下内容:

import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.n'.format(count)

在此示例中,redis 是应用程序网络上的 redis 容器的主机名,该主机使用的端口为 6379。

在 composetest 目录中创建另一个名为 requirements.txt 的文件,内容如下:

flask
redis

2、创建 Dockerfile 文件

在 composetest 目录中,创建一个名为的文件 Dockerfile,内容如下:

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]

3、创建 docker-compose.yml

在测试目录中创建一个名为 docker-compose.yml 的文件,然后粘贴以下内容:

# yaml 配置
version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"

4、使用 Compose 命令构建和运行您的应用

在测试目录中,执行以下命令来启动应用程序:

docker-compose up

如果你想在后台执行该服务可以加上 -d 参数:

docker-compose up -d

(目录下要有Dockerfile,docker-compose.yml,其他需要用到的文件)

nvidia-docker

运行容器

# --shm-size 16G将tmpfs的大小改为16G(内存空间)
docker run --runtime=nvidia --gpus all --shm-size 16G -it -d --name 容器名 镜像名

/dev/shm/介绍:

/dev/shm/是linux下一个非常有用的目录,因为这个目录不在硬盘上,而是在内存里。默认系统就会加载/dev/shm ,它就是所谓的tmpfs

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐