Docker入门基础知识

目录

Docker相关的概念

1.1 虚拟机和容器

借助于VMWare等软件,可以在一台计算机上创建多个虚拟机,每个虚拟机都拥有独立的操作系统,可以各自独立的运行程序。这种分身术虽然隔离度高(操作系统级),使用方便(类似物理机),但占用存储资源多(GB级)、启动速度慢(分钟级)的缺点也是显而易见的。

相较于虚拟机,容器(Container)是一种轻量型的虚拟化技术,它虚拟的是最简运行环境(类似于沙盒)而非操作系统,启动速度快(秒级)、占用存储资源少(KB级或MB级),容器间隔离度为进程级。在一台计算机上可以运行上千个容器,这是容器技术对虚拟机的碾压式优势。

1.2 容器、镜像和Docker

Docker是一个开源的应用容器引擎,可以创建容器以及基于容器运行的程序。Docker可以让开发者打包他们的应用和依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。在Docker和容器之间,还隐藏着一个镜像的概念。本质上,Docker镜像是一个特殊的文件系统,它提供容器运行时所需的程序、库、资源、配置等文件。Docker镜像类似于一个py文件,它需要Docker的运行时(类似于Python解释器)运行。镜像被运行时,即创建了一个镜像的实例,一个实例就是一个容器。

镜像 是一个构建容器的只读模板,是一个包含了应用程序和其运行时依赖环境的只读文件。它包含了容器启动所需的所有信息,包括运行程序和配置数据。每一个镜像由一系列的层 (layers) 组成。Docker 使用 UnionFS 来将这些层联合到单独的镜像中。UnionFS 允许独立文件系统中的文件和文件夹(称之为分支)被透明覆盖,形成一个单独连贯的文件系统。正因为有了这些层的存在,Docker 是如此的轻量。当你改变了一个 Docker 镜像,比如升级到某个程序到新的版本,一个新的层会被创建。因此,不用替换整个原先的镜像或者重新建立(在使用虚拟机的时候你可能会这么做),只是一个新的层被添加或升级了。现在你不用重新发布整个镜像,只需要升级,层使得分发 Docker 镜像变得简单和快速。

容器 容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。Docker 利用容器来运行应用。一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行部分。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

注: 镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

20230329151449

运行容器实例有两种方式:

交互型容器: 前台运行,可以通过控制台与容器交互。如果创建该容器的终端被关闭,则容器就变为停止状态。此外,在容器控制台中输入exit或者通过docker stop或docker kill也能终止容器。 后台型容器: 后台运行,创建启动之后就与终端无关了,需要用 docker stop 或 docker kill 来终止,或者 docker logs 查看运行中的输出。 仓库 Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。同样的,Docker 仓库也有公有和私有的概念。公有的 Docker 仓库名字是 Docker Hub。Docker Hub 提供了庞大的镜像集合供使用。这些镜像可以是自己创建,或者在别人的镜像基础上创建。Docker 仓库是 Docker 的分发部分。

Docker 仓库的概念与 Git 版本控制工具有些类似,注册服务器可以理解为 GitHub 这样的托管服务。

Docker的安装

2.1 在ubuntu中安装

在linux系统中安装Docker非常简单,官方为我们提供了一键安装脚本。这个方法也适用于Debian或CentOS等发行版。

curl -sSL https://get.daocloud.io/docker | sh

安装过程如果出现超时,不要灰心,多试几次,总会成功的。安装完成后,Docker只能被root用户使用,可以使用下面的命令取消权限限制:

sudo gpasswd -a <你的用户名> docker

然后,重启docker服务:

sudo service docker restart

最后,关闭当前的命令行,重新打开新的命令行就可以了。

Docker镜像的使用

docker官方的镜像库比较慢,在进行镜像操作之前,需要将镜像源设置为国内的站点。

新建文件/etc/docker/daemon.json,输入如下内容:

{
    "registry-mirrors" : [
        "https://registry.docker-cn.com",
        "https://docker.mirrors.ustc.edu.cn",
        "http://hub-mirror.c.163.com",
        "https://cr.console.aliyun.com/"
    ]
}

然后重启docker的服务:

systemctl restart docker

3.1 列出本地所有镜像

执行命令 docker images 可以查看

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              20.04               f643c72bc252        5 weeks ago         72.9MB
hello-world         latest              bf756fb1ae65        12 months ago       13.3kB

当前我本地只有刚才安装的两个镜像。

3.2 从镜像库中查找镜像

执行命令 docker search 镜像名称可以从docker镜像库中查找镜像。

$ docker search python
NAME                             DESCRIPTION                                     STARS              OFFICIAL          AUTOMATED
python                           Python is an interpreted, interactive, objec…   5757                [OK]                
django                           Django is a free web application framework, …   1039                [OK]                
pypy                             PyPy is a fast, compliant alternative implem…   260                 [OK]                
joyzoursky/python-chromedriver   Python with Chromedriver, for running automa…   57                                      [OK]
nikolaik/python-nodejs           Python with Node.js                             57                                      [OK]
arm32v7/python                   Python is an interpreted, interactive, objec…   53                                      
circleci/python                  Python is an interpreted, interactive, objec…   42                                      
centos/python-35-centos7         Platform for building and running Python 3.5…   38                                      
centos/python-36-centos7         Platform for building and running Python 3.6…   30                                      
hylang                           Hy is a Lisp dialect that translates express…   29                  [OK]                
arm64v8/python                   Python is an interpreted, interactive, objec…   24                                      
revolutionsystems/python         Optimized Python Images                         18                                      
centos/python-27-centos7         Platform for building and running Python 2.7…   17                                      
bitnami/python                   Bitnami Python Docker Image                     10                                      [OK]
publicisworldwide/python-conda   Basic Python environments with Conda.           6                                       [OK]
d3fk/python_in_bottle            Simple python:alpine completed by Bottle+Req…   5                                       [OK]
dockershelf/python               Repository for docker images of Python. Test…   5                                       [OK]
clearlinux/python                Python programming interpreted language with…   4                                       
i386/python                      Python is an interpreted, interactive, objec…   3                                       
ppc64le/python                   Python is an interpreted, interactive, objec…   2                                       
centos/python-34-centos7         Platform for building and running Python 3.4…   2                                       
amd64/python                     Python is an interpreted, interactive, objec…   1                                       
ccitest/python                   CircleCI test images for Python                 0                                       [OK]
s390x/python                     Python is an interpreted, interactive, objec…   0                                       
saagie/python                    Repo for python jobs                            0

最好选择官方(OFFICIAL)的镜像,这样的镜像最稳定一些。

3.3 下载新的镜像

执行命令docker pull 镜像名称:版本号即可下载新的镜像。

$ docker pull python:3.8
3.8: Pulling from library/python
6c33745f49b4: Pull complete 
ef072fc32a84: Pull complete 
c0afb8e68e0b: Pull complete 
d599c07d28e6: Pull complete 
f2ecc74db11a: Pull complete 
26856d31ce86: Pull complete 
2cd68d824f12: Pull complete 
7ea1535f18c3: Pull complete 
2bef93d9a76e: Pull complete 
Digest: sha256:9079aa8582543494225d2b3a28fce526d9a6b06eb06ce2bac3eeee592fcfc49e
Status: Downloaded newer image for python:3.8
docker.io/library/python:3.8

镜像下载后,就可以使用镜像来创建容器了。

Docker容器的使用

4.1 启动容器

执行命令docker run即可启动容器,也就是创建某个镜像的实例。docker run命令非常复杂,可以先执行一个docker run –help来查看帮助:

$ docker run --help

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Run a command in a new container

Options:
      --add-host list                  Add a custom host-to-IP mapping (host:ip)
  -a, --attach list                    Attach to STDIN, STDOUT or STDERR
      --blkio-weight uint16            Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
      --blkio-weight-device list       Block IO weight (relative device weight) (default [])
      --cap-add list                   Add Linux capabilities
      --cap-drop list                  Drop Linux capabilities
      --cgroup-parent string           Optional parent cgroup for the container
      --cidfile string                 Write the container ID to the file
      --cpu-period int                 Limit CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int                  Limit CPU CFS (Completely Fair Scheduler) quota
      --cpu-rt-period int              Limit CPU real-time period in microseconds
      --cpu-rt-runtime int             Limit CPU real-time runtime in microseconds
  -c, --cpu-shares int                 CPU shares (relative weight)
      --cpus decimal                   Number of CPUs
      --cpuset-cpus string             CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string             MEMs in which to allow execution (0-3, 0,1)
  -d, --detach                         Run container in background and print container ID
      --detach-keys string             Override the key sequence for detaching a container
      --device list                    Add a host device to the container
      --device-cgroup-rule list        Add a rule to the cgroup allowed devices list
      --device-read-bps list           Limit read rate (bytes per second) from a device (default [])
      --device-read-iops list          Limit read rate (IO per second) from a device (default [])
      --device-write-bps list          Limit write rate (bytes per second) to a device (default [])
      --device-write-iops list         Limit write rate (IO per second) to a device (default [])
      --disable-content-trust          Skip image verification (default true)
      --dns list                       Set custom DNS servers
      --dns-option list                Set DNS options
      --dns-search list                Set custom DNS search domains
      --domainname string              Container NIS domain name
      --entrypoint string              Overwrite the default ENTRYPOINT of the image
  -e, --env list                       Set environment variables
      --env-file list                  Read in a file of environment variables
      --expose list                    Expose a port or a range of ports
      --gpus gpu-request               GPU devices to add to the container ('all' to pass all GPUs)
      --group-add list                 Add additional groups to join
      --health-cmd string              Command to run to check health
      --health-interval duration       Time between running the check (ms|s|m|h) (default 0s)
      --health-retries int             Consecutive failures needed to report unhealthy
      --health-start-period duration   Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) (default 0s)
      --health-timeout duration        Maximum time to allow one check to run (ms|s|m|h) (default 0s)
      --help                           Print usage
  -h, --hostname string                Container host name
      --init                           Run an init inside the container that forwards signals and reaps processes
  -i, --interactive                    Keep STDIN open even if not attached
      --ip string                      IPv4 address (e.g., 172.30.100.104)
      --ip6 string                     IPv6 address (e.g., 2001:db8::33)
      --ipc string                     IPC mode to use
      --isolation string               Container isolation technology
      --kernel-memory bytes            Kernel memory limit
  -l, --label list                     Set meta data on a container
      --label-file list                Read in a line delimited file of labels
      --link list                      Add link to another container
      --link-local-ip list             Container IPv4/IPv6 link-local addresses
      --log-driver string              Logging driver for the container
      --log-opt list                   Log driver options
      --mac-address string             Container MAC address (e.g., 92:d0:c6:0a:29:33)
  -m, --memory bytes                   Memory limit
      --memory-reservation bytes       Memory soft limit
      --memory-swap bytes              Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --memory-swappiness int          Tune container memory swappiness (0 to 100) (default -1)
      --mount mount                    Attach a filesystem mount to the container
      --name string                    Assign a name to the container
      --network network                Connect a container to a network
      --network-alias list             Add network-scoped alias for the container
      --no-healthcheck                 Disable any container-specified HEALTHCHECK
      --oom-kill-disable               Disable OOM Killer
      --oom-score-adj int              Tune host's OOM preferences (-1000 to 1000)
      --pid string                     PID namespace to use
      --pids-limit int                 Tune container pids limit (set -1 for unlimited)
      --platform string                Set platform if server is multi-platform capable
      --privileged                     Give extended privileges to this container
  -p, --publish list                   Publish a container's port(s) to the host
  -P, --publish-all                    Publish all exposed ports to random ports
      --read-only                      Mount the container's root filesystem as read only
      --restart string                 Restart policy to apply when a container exits (default "no")
      --rm                             Automatically remove the container when it exits
      --runtime string                 Runtime to use for this container
      --security-opt list              Security Options
      --shm-size bytes                 Size of /dev/shm
      --sig-proxy                      Proxy received signals to the process (default true)
      --stop-signal string             Signal to stop a container (default "SIGTERM")
      --stop-timeout int               Timeout (in seconds) to stop a container
      --storage-opt list               Storage driver options for the container
      --sysctl map                     Sysctl options (default map[])
      --tmpfs list                     Mount a tmpfs directory
  -t, --tty                            Allocate a pseudo-TTY
      --ulimit ulimit                  Ulimit options (default [])
  -u, --user string                    Username or UID (format: <name|uid>[:<group|gid>])
      --userns string                  User namespace to use
      --uts string                     UTS namespace to use
  -v, --volume list                    Bind mount a volume
      --volume-driver string           Optional volume driver for the container
      --volumes-from list              Mount volumes from the specified container(s)
  -w, --workdir string                 Working directory inside the container

比如我们要执行python的shell,需要添加-it参数,即:docker run -it python:3.8

$ docker run -it python:3.8 
Python 3.8.7 (default, Dec 22 2020, 18:46:25) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

4.2 将宿主机的文件挂载到容器

docker容器与宿主机是隔离的,要想让容器内的程序能访问宿主机上的文件,需要通过-v参数将宿主机的文件挂载到容器中。

比如我们在宿主机上有一个hello.py,可以打印hello,想要在python容器中执行,就需要进行挂载。-v后还需要接两个参数,分别是宿主机的目录和容器内的目录,两者使用:分隔,路径必须都是绝对路径。

我的hello.py保存在主目录的/docker_test目录中,将这个目录挂载到容器的/docker_test目录,然后在容器内执行python /docker_test/hello.py:

$ docker run -v ~/docker_test:/docker_test python:3.8 python /docker_test/hello.py
hello

4.3 容器管理

上面的服务运行之后,可以使用docker ps命令,查看运行中的容器:

$ docker ps
CONTAINER ID     IMAGE           COMMAND                  CREATED           STATUS         PORTS                    NAMES
ec4c86b8a163     python:3.8      "python /docker_test…"   5 seconds ago     Up 4 seconds   0.0.0.0:5000->5000/tcp   eager_wilson

显示的内容有下面几列:

  • CONTAINER ID:容器ID
  • IMAGE:镜像名称和版本
  • COMMAND:执行的命令
  • CREATED:容器创建时间
  • STATUS:容器的状态
  • PORTS:端口映射
  • NAMES:容器名

要想结束容器,可以使用docker kill 容器ID命令。

自制Docker镜像

一般而言,当我们的程序开发完成后,会连同程序文件与运行环境一起制作成一个新的镜像。

要制作镜像,需要编写Dockerfile。DockeFile由多个命令组成,常用的命令有:

  • FROM:基于某个镜像来制作新的镜像。格式为:FROM 镜像名称:镜像版本。
  • COPY:从宿主机复制文件,支持?、*等通配符。格式为:COPY 源文件路径 目标文件路径。
  • ADD:从宿主机添加文件,格式与COPY相同,区别在于当文件为压缩文件时,会解压缩到目标路径。
  • RUN:在创建新镜像的过程中执行的shell命令。格式为:RUN shell命令行。注意,此shell命令将在容器内执行。
  • CMD:在容器实例中运行的命令,格式与RUN相同。注意,如果在docker run时指定了命令,将不会执行CMD的内容。
  • ENTRYPOINT:在容器实例中运行的命令,格式与CMD相同。注意,如果在docker run时指定了命令,该命令会以命令行参数的形式传递到ENTRYPOINT中。
  • ENV:在容器中创建环境变量,格式为:ENV 变量名值。

注意,Docker镜像中有一个层的概念,每执行一个RUN命令,就会创建一个层,层过多会导致镜像文件体积增大。尽量在RUN命令中使用&&连接多条shell命令,减少RUN命令的个数,可以有效减小镜像文件的体积。

5.1 自制显示文本文件内容镜像

编写cat.py,接收一个文件名,由python读取文件并显示文件的内容:

import os
import sys

input = sys.argv[1]

with open(input, "r") as fp:
    print(fp.read())

这个例子比较简单,缩写Dockerfile如下:

FROM python:3.8
WORKDIR /files
COPY cat.py /cat.py
ENTRYPOINT ["python", "/cat.py"]

这个Dockerfile的含义是:

  • 以python:3.8为基础镜像
  • 容器启动命令的工作目录为/files,在运行镜像时,需要我们把宿主机的某目录挂载到容器的/files目录
  • 复制cat.py到容器的根目录下
  • 启动时运行python /cat.py命令

需要说明的是,ENTRYPOINT有两种写法:

ENTRYPOINT python /cat.py
ENTRYPOINT ["python", "/cat.py"]

这里采用第二种写法,是因为我们要在外部给容器传递参数。执行命令编译Docker镜像:

docker build -t cat:1.0 .

这个命令中,-t的含义是目标,即生成的镜像名为hello,版本号为1.0,别忘了最后那个.,这叫到上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

这样,我们的第一个镜像就制作完成了,使用下面的命令执行它:

docker run -it -v ~/docker_test/cat/files:/files cat:1.0 test.txt

即可看到~/docker_test/cat/files/test.txt的内容。

5.2 用 Docker 部署一个 Python 应用

使用 Docker 部署应用的常规流程是:

  • 开发项目并本地测试通过
  • 编写 Dockerfile 放置到项目根目录
  • 打包镜像文件
  • 运行镜像容器
  • 测试

为了演示方便,这里以一个简单的 Flask 项目为例进行讲解

项目开发
from flask import Flask

# 安装依赖
# pip3 install -U flask

app = Flask(__name__)


@app.route('/')
def index():
    return "测试容器部署!"


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888)

# 浏览器访问测试
# http://127.0.0.1:8888/

项目开发完成,并在本地测试通过后就可以编写 Dockerfile 文件了

编写 Dockerfile

在项目根目录下,创建一个 Dockerfile 文件,使用上面的指令编写描述脚本

需要注意的是,这里使用「 EXPOSE 」指令暴露的端口号与入口文件定义的端口号保持一致

# Dockerfile

FROM centos:7.9.2009
RUN yum makecache fast;
RUN yum install python3-devel python3-pip -y
RUN pip3 install -i https://pypi.douban.com/simple flask
COPY main.py /opt
WORKDIR /opt
EXPOSE 8888
CMD ["python3","main.py"]
构建镜像
# 在当前文件夹下,根据Dockerfile文件构建一个镜像
# 镜像名称:xag/my_flask_web
# --no-cache:不使用旧的缓存进行镜像构建
docker build --no-cache -t "xag/my_flask_web" .
运行镜像容器

使用 docker run 命令基于镜像运行一个容器

其中

  • -d:代表容器在后台运行,不是基于前台运行
  • –name:用于执行容器的别名
  • -p:用于配置宿主机与容器的端口映射
# -d:后台运行
# 宿主机(9999)映射容器内的8888(上面Dockerfile已经暴露了8888端口)
docker run -d --name flask_web -p 9999:8888 xag/my_flask_web  
测试一下

最后在浏览器中,通过宿主机暴露的端口号 9999 访问项目了

访问地址:http://127.0.0.1:9999/

导入镜像到生产环境

到此,我们的镜像已经制作好了,可是,镜像文件在哪,如何在生产环境下运行呢?

刚才使用docker images命令时,已经看到了生成的镜像:

$ docker images                          
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello               1.0                 01fe19111dc7        59 minutes ago      893MB
python              3.8                 f5041c8ae6b1        13 days ago         884MB
ubuntu              20.04               f643c72bc252        5 weeks ago         72.9MB
hello-world         latest              bf756fb1ae65        12 months ago       13.3kB

我们可以使用docker save命令将镜像保存到指定的文件中,保存的文件是一个.tar格式的压缩文件:

docker save -o hello.tar hello:1.0

将hello.tar复制到生产环境的机器上,然后执行导入命令:

docker load -i hello.tar

就可以使用了。

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦