Docker 入门 (一)

249 阅读14分钟

docker

官网

容器化

容器化意味着封装或打包软件代码及其所有依赖项,以便它可以在任何基础架构上统一且一致地运行。

什么是docker

Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。 它是目前最流行的 Linux 容器解决方案。

和虚拟化技术类似,它极大的方便了应用服务的部署;又与虚拟化技术不同,它以一种更轻量的方式实现了应用服务的打包。使用 Docker 可以让每个应用彼此相互隔离,在同一台机器上同时运行多个应用,不过他们彼此之间共享同一个操作系统。Docker 的优势在于,它可以在更细的粒度上进行资源的管理,也比虚拟化技术更加节约资源。

历史

2010 年,几个搞 IT 的年轻人,在美国旧金山成立了一家名叫 dotCloud 的公司。dotCloud 的平台即服务(Platform-as-a-Service, PaaS)提供商。底层技术上,dotCloud 平台利用了 Linux 的 LXC 容器技术。

Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源。

为了方便创建和管理这些容器,dotCloud 基于 Google 公司推出的 Go 语言开发了一套内部工具,之后被命名为 Docker。Docker 就是这样诞生的。

2013 年 3 月,开源。

越来越多的人发现docker的优点!火了。Docker每个月都会更新一个版本!

docker 优势

(1)更高效的利用系统资源 相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。

(2)更快速的启动时间。 传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。

(3)一致的运行环境。 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。。

(4)持续交付和部署。 使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。

下面的图片比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

duibi.png

docker 安装

mac

MAC 安装 docker

注意区分是 intel 还是 M1 的cpu

mac-install.png

linux centos7

centos7 安装 docker

  1. 卸载当前已经存在的旧版 Docker
 sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 添加Docker安装源
 sudo yum install -y yum-utils
 sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
  1. 安装最新版本
 sudo yum install docker-ce docker-ce-cli containerd.io

如果需要安装指定版本,可以通过下面命令查看版本并选择需要的版本

yum list docker-ce --showduplicates | sort -r
 sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
  1. 安装完成,启动Docker
 sudo systemctl start docker
  1. 先跑一个 helloworld
$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

卸载 Docker

#1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2. 删除资源
rm -rf /var/lib/docker
# /var/lib/docker 是docker的默认工作目录

Docker核心概念

  • 镜像ImageDocker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。

  • 容器Container) 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间 (opens new window).

  • 仓库Repository) 镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

一个 Docker Registry 中可以包含多个 仓库Repository);每个仓库可以包含多个 标签Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

仓库名经常以 两段式路径 形式出现,比如 fourtharsenal/liyunfei,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。

cangku.png

Docker 是怎样工作的

Docker Engine是一个C/S架构的应用程序,主要包含下面几个组件;

Docker 守护程序: 守护程序(dockerd)是一个始终在后台运行并等待来自客户端的命令的进程。守护程序能够管理各种 Docker 对象。

Docker 客户端: 客户端(docker)是一个命令行界面程序,主要负责传输用户发出的命令。

REST API: REST API 充当守护程序和客户端之间的桥梁。使用客户端发出的任何命令都将通过 API 传递,最终到达守护程序。

d62a6059252dd42a5f9be61dc52818b0c8eab88b.png

Docker使用了C/S体系架构,Docker客户端与Docker守护进程通信,Docker守护进程负责构建,运行和分发Docker容器。 Docker客户端和守护进程使用REST API通过UNIX套接字或网络接口进行通信。

c2fdfc039245d68881eae9196cd13e1bd31b24bf.png

Docker基础命令操作

官方文档

docker version #显示docker的版本信息。
docker info #显示docker的系统信息,包括镜像和容器的数量

查看帮助命令

docker [命令] --help
# 查看 docker pull 帮助文档
docker pull --help

Usage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Pull an image or a repository from a registry

Options:
  -a, --all-tags                Download all tagged images in the repository
      --disable-content-trust   Skip image verification (default true)
      --platform string         Set platform if server is multi-platform capable
  -q, --quiet                   Suppress verbose output

Docker镜像相关操作

Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。

docker search # 搜索镜像
docker pull #下载镜像 docker image pull
docker images # 查看所有本地主机上的镜像 docker image ls
docker rmi # 删除镜像 docker image rm

搜索官方仓库镜像

docker search centos

NAME                       DESCRIPTION                                     STARS     `OFFICIAL` AUTOMATED
centos                     The official build of CentOS.                   6753      `[OK]`
ansible/centos7-ansible    Ansible on Centos7                              134                  [OK]
consol/centos-xfce-vnc     Centos container with "headless" VNC session…   130                  [OK]

拉取镜像

命令:$ docker pull [Docker Registry 地址[:端口号]/]仓库名[:标签]

说明:

  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub(docker.io)。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
# 拉取 centos 镜像
docker pull centos
Using default tag: latest
latest: Pulling from library/centos
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Image is up to date for centos:latest
docker.io/library/centos:latest

查看当前主机的镜像列表

docker image ls
docker images

-a, --all Show all images (default hides intermediate images) #列出
所有镜像
-q, --quiet Only show numeric IDs # 只显示镜像的id
$ docker image ls
REPOSITORY                        TAG       IMAGE ID       CREATED             SIZE
fourtharsenal/docker101tutorial   latest    f82bbbe08672   About an hour ago   28.3MB
docker101tutorial                 latest    f82bbbe08672   About an hour ago   28.3MB
mysql                             5.7       1d7aba917169   12 days ago         448MB

列表包含了 仓库名标签镜像 ID创建时间 以及 所占用的空间

列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。

  • 镜像体积查看docker system df
  • 显示镜像摘要:docker image ls --digests

删除本地镜像

docker rmi [OPTIONS] IMAGE [IMAGE...] dockder image rm

-f, --force Force removal of the image

<镜像> 可以是 镜像ID镜像名 或者 镜像摘要

$ docker rmi mysql:5.7
Untagged: mysql:5.7
Untagged: mysql@sha256:d9b934cdf6826629f8d02ea01f28b2c4ddb1ae27c32664b14867324b3e5e1291
Deleted: sha256:1d7aba9171693947d53f474014821972bf25d72b7d143ce4af4c8d8484623417
Deleted: sha256:94ebbead5c58282fef91cc7d0fb56e4006a72434b4a6ae2cd5be98f369cb8c21
Deleted: sha256:989da5efad29ec59bd536cd393d277bc777f8b9b34b8e3ad9593a4b0a83b40f4
Deleted: sha256:7457ee6817c678da3cb383d27a3d79d5f3f25fbcb92958d5e8d5709e7631e23c
Deleted: sha256:fe7dac53adebe33519b4e4fc577bfcddd7372cc313c35fae681fc82fb325fdc0

删除所有镜像

docker rmi $(docker image ls -q)

docker commit

使用 docker commit 从容器生成镜像,但是实际环境中并不会这样使用。定制镜像应该使用 Dockerfile 来完成。 Dockerfile 会在第二篇文章中介绍

docker build

通过dockerfile创建容器镜像, dockerfile会在第二篇文章中介绍

配置镜像加速

对于使用 macOS 的用户, 在任务栏点击 Docker Desktop 应用图标 -> Perferences,在左侧导航菜单选择 Docker Engine,在右侧像下边一样编辑 json 文件。修改完成之后,点击 Apply & Restart 按钮,Docker 就会重启并应用配置的镜像地址了。

mac

{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}

Docker 容器相关操作

容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个容器层,该层允许修改镜像的整个副本。

docker-container.png

容器的生命周期

容器的生命周期是容器可能处于的状态

  1. created:初建状态
  2. running:运行状态
  3. stopped:停止状态
  4. paused: 暂停状态
  5. deleted:删除状态

列出所有运行的容器

docker psdocker container ls命令 列出当前正在运行的容器

# 查看帮助文档
docker container ls --help
-a, --all Show all containers (default shows just running)
-n, --last int Show n last created containers (includes all states) (default -1)
-q, --quiet Only display numeric IDs

# -a 显示所有容器
docker ps -a

CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS                          PORTS                                   NAMES
32ac47a2d0a6   nginx         "/docker-entrypoint.…"   22 seconds ago       Up 21 seconds                   0.0.0.0:8088->80/tcp, :::8088->80/tcp   webserver
d46790b9f194   hello-world   "/hello"                 About a minute ago   Exited (0) About a minute ago                                           crazy_fermat

启动容器

docker create创建容器, 创建的容器处于停止状态

docker create -it --name=busybox busybox

# 查看容器
docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS    PORTS     NAMES
e055978e44bf   busybox   "sh"      26 seconds ago   Created             busybox

docker start 命令基于已经创建好的容器直接启动

docker start busybox
busybox
# 查看容器
docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED              STATUS         PORTS     NAMES
e055978e44bf   busybox   "sh"      About a minute ago   Up 7 seconds             busybox

使用docker run命令直接基于镜像新建一个容器并启动,相当于先执行docker create命令从镜像创建容器,然后再执行docker start命令启动容器。

查看帮助文档

docker run --help

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

Run a command in a new container

docker run用来启动一个新的容器并运行一个命令

启动一个busybox容器并在容器中执行sh命令

docker run -it --name box1 busybox  sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ #

参数说明

  • -i 或 --interactive 连接到容器的输入流,以便可以将输入发送到 bash

  • -t 或 --tty 选项可通过分配伪 tty 来格式化展示并提供类似本机终端的体验

  • --name 'Name' 容器名字

  • -d 后台运行

    在上面的示例中,为了使容器继续运行,必须将终端窗口保持打开状态。关闭终端窗口会停止正在运行的容器。

  • -p 主机端口:容器端口 -P 会随机分配一个端口 运行一个nginx容器

docker run -d -P --name nginx nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
a330b6cecb98: Pull complete
e0ad2c0621bc: Pull complete
9e56c3e0e6b7: Pull complete
09f31c94adc6: Pull complete
32b26e9cdb83: Pull complete
20ab512bbb07: Pull complete
Digest: sha256:853b221d3341add7aaadf5f81dd088ea943ab9c918766e295321294b035f3f3e
Status: Downloaded newer image for nginx:latest
e9b80ca47658f4a04864943ca686db81e35a1baac1e1c63b78e16d039ec6e5a8

查看容器

docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e9b80ca47658   nginx     "/docker-entrypoint.…"   37 seconds ago   Up 36 seconds   0.0.0.0:55000->80/tcp, :::55000->80/tcp   nginx

可以看到本机的55000端口映射到了容器的80端口,此时访问localhost:55000

截屏2021-09-27 下午5.21.47.png

终止容器

docker pause 暂停容器 docker stopdocker kill 停止容器

# `暂停`容器
docker pause CONTAINER [CONTAINER...]
# `停止`容器
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker kill

stop 命令通过发送信号SIGTERM 来正常关闭容器。如果容器在一定时间内没有停止运行,则会发出 SIGKILL 信号,该信号会立即关闭容器。 docker kill 直接发送 SIGKILL 信号

暂停nginx容器, 此时访问localhost:55000就无法访问到页面

docker pause nginx

重新启动容器,此时可以访问localhost:55000

docker unpause nginx

终止容器,然后再启动容器,因为-P会随机指定端口号,此时端口号有变化,查看,此时映射的端口为55001

 docker stop nginx
nginx
docker start nginx
nginx
docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS         PORTS                                     NAMES
e9b80ca47658   nginx     "/docker-entrypoint.…"   13 minutes ago   Up 8 seconds   0.0.0.0:55001->80/tcp, :::55001->80/tcp   nginx

进入容器

docker exec 进入运行中的容器

退出容器

exit #容器直接退出
ctrl +P +Q #容器不停止退出

命令文档

docker exec --help

Usage:  docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

Run a command in a running container

进入nginx 容器

 docker exec -it nginx sh
# ls
bin  boot  dev	docker-entrypoint.d  docker-entrypoint.sh  etc	home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

删除容器

docker container rmdocker rm 删除暂停状态或终止状态的容器

docker rm [OPTIONS] CONTAINER [CONTAINER...]
  -f, --force     Force the removal of a running container (uses SIGKILL)

强制删除运行中的容器添加-f

导入容器

使用docker export CONTAINER命令导出一个容器到文件,不管此时该容器是否处于运行中的状态。

# 导出容器前我们先进入容器,创建一个文件,
docker exec -it busybox2 sh
cd /tmp && touch test
docker export busybox2 > busybox.tar
ls
busybox.tar       docs              node_modules      package-lock.json package.json      yarn.lock
# 使用docker import命令导入容器 
# busybox.tar 被导入成为新的镜像,镜像名称为 busybox:test
docker import busybox.tar busybox:test
sha256:55ebe2ae97c68d9cd22f4f102e3235bcba634dc6ab3bbffa5e33aa893e7b38f1
# 使用docker run命令启动
docker run -it busybox:test sh

重命名容器

docker rename

查看容器详细信息

docker inspect

实时监控容器资源数据

docker stats

容器与宿主机之间的数据拷贝

docker cp
# 拷贝宿主机文件
docker cp /Users/liyf/learn/docker/docker-docs busybox2:/test123
ls
busybox.tar       docs              node_modules      package-lock.json package.json      yarn.lock
# 进入容器
docker exec -it busybox2 sh
/ # ls
bin       dev       etc       home      proc      root      sys       test.txt  test123   tmp       usr       var
/ # cd test123/
/test123 # ls
busybox.tar        docs               node_modules       package-lock.json  package.json       yarn.lock
/test123 #

容器操作总结:

20200503135132719.png

REPOSITORY

Docker hub 是当前全球最大的镜像市场,差不多超过 10w 个容器镜像,大部分操作系统镜像都来自于此。 仓库(Repository)是集中存放镜像的地方。

一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 docker.io/ubuntu 来说,docker.io 是注册服务器地址,ubuntu 是仓库名。

docker hub

dockerHub注册账号

登录

docker login
-u, --username string   username
# 退出
docker logout

推送镜像

docker push
Usage:  docker push [OPTIONS] NAME[:TAG]