【docker】Docker核心技术快速入门及私有仓库搭建

更多内容请点击 我的博客 查看,欢迎来访。

什么是Docker?

官方文档翻译

Docker 是基于Go语言实现的开源容器项目。利用操作系统本身已有的机制和特性,可以实现远超传统虚拟机的轻量级虚拟化。它是内核级的虚拟化。期望达到使项目运行环境“一次封装,到处运行的目的”。

Docker作为一个软件集装箱化平台,可以让开发者构建应用程序时,将它与其依赖环境一起打包到一个容器中,然后很容易地发布和应用到任意平台中。

利用docker创建的运行环境叫做docker容器,容器是通过docker镜像创建的,docker镜像文件可以放在私有仓库中也可以放在共有仓库中。最大的公有仓库是官方Docker Hub。

思想

  • 集装箱
  • 标准化
  • 隔离

核心

docker有3大核心:镜像、容器、仓库。

为什么要使用 Docker?

作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。

更高效的利用系统资源

由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。

更快速的启动时间

传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。

一致的运行环境

开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。

持续交付和部署

对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行

使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。

而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。

更轻松的迁移

由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

更轻松的维护和扩展

Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。

对比传统虚拟机总结

特性 容器 虚拟机
启动 秒级 分钟级
硬盘使用 一般为 MB 一般为 GB
性能 接近原生 弱于
系统支持量 单机支持上千个容器 一般几十个

架构

【docker】Docker核心技术快速入门及私有仓库搭建_第1张图片

基本概念

镜像

轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。包含运行某个软件所需的所有内容,包含代码、运行时、库、环境变量和配置文件。

操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。

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

分层存储
因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

镜像特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,容器层之下的都叫镜像层。镜像分层叠加,构成Docker镜像。

容器

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

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。

前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层。

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

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

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

可以把容器看成一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序
容器的定义和镜像几乎一样,也是一堆层的统一视角,唯一的区别在于容器的最上层是可读可写的。

仓库

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

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

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

以 Ubuntu 镜像 为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04。我们可以通过 ubuntu:16.04,或者 ubuntu:18.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest。

仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务。

Docker Registry 公开服务
Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并拥有大量的高质量的官方镜像。除此以外,还有 CoreOS 的 Quay.io,CoreOS 相关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像使用的就是这个服务。

由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为加速器。常见的有 阿里云加速器、DaoCloud 加速器 等。使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从 Docker Hub 下载速度会提高很多。在 安装 Docker 一节中有详细的配置方法。

国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库 等。

私有 Docker Registry
除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。在 私有仓库 一节中,会有进一步的搭建私有 Registry 服务的讲解。

开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。在官方的商业化版本 Docker Trusted Registry 中,提供了这些高级功能。

除了官方的 Docker Registry 外,还有第三方软件实现了 Docker Registry API,甚至提供了用户界面以及一些高级功能。比如,Harbor 和 Sonatype Nexus。

配置Docker环境

安装Docker

安装环境为CentOS7

可以在 https://docs.docker.com/install/linux/docker-ce/centos/ 找到安装文档

# 安装依赖
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
[root@localhost ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 如果官方源安装下载慢就换
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# yum install docker-ce docker-ce-cli containerd.io -y
[root@localhost ~]# systemctl enable docker
[root@localhost ~]# systemctl start docker

docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。

[root@localhost ~]# groupadd docker
groupadd:“docker”组已存在
[root@localhost ~]# usermod -aG docker $USER

安装完成

[root@localhost ~]# docker info
Client:
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 19.03.7
 Storage Driver: overlay2
  Backing Filesystem: <unknown>
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 3.10.0-1062.4.1.el7.x86_64
 Operating System: CentOS Linux 7 (Core)
 OSType: linux
 Architecture: x86_64
 CPUs: 1
 Total Memory: 972.4MiB
 Name: localhost.localdomain
 ID: KVPR:Z3C3:36GW:UBAP:QJ4R:D2OS:AGPZ:IB7X:O4VK:TQNZ:BODA:HFO3
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

镜像加速

内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。国内很多云服务商都提供了国内加速器服务,例如:

  • Azure 中国镜像 https://dockerhub.azk8s.cn
  • 阿里云加速器(需登录账号获取)
  • 网易云加速器 https://hub-mirror.c.163.com

对于CentOS7系统

[root@localhost ~]# vim /etc/docker/daemon.json

# 添加以下内容
{
     
  "registry-mirrors": [
    "https://dockerhub.azk8s.cn",
    "https://hub-mirror.c.163.com"
  ]
}

然后重启Docker

[root@localhost ~]# systemctl restart docker
[root@localhost ~]# docker info
Client:
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 19.03.7
 Storage Driver: overlay2
  Backing Filesystem: <unknown>
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 3.10.0-1062.4.1.el7.x86_64
 Operating System: CentOS Linux 7 (Core)
 OSType: linux
 Architecture: x86_64
 CPUs: 1
 Total Memory: 972.4MiB
 Name: localhost.localdomain
 ID: KVPR:Z3C3:36GW:UBAP:QJ4R:D2OS:AGPZ:IB7X:O4VK:TQNZ:BODA:HFO3
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  https://dockerhub.azk8s.cn/
  https://hub-mirror.c.163.com/
 Live Restore Enabled: false

可以看到Registry Mirrors已经替换成了自定义的链接。

测试镜像使用

root@localhost ~]# docker run hello-world
# run的时候现在本地找是否有这个镜像
Unable to find image 'hello-world:latest' locally
# 如果没有就去Docker hub中下载
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:fc6a51919cfeb2e6763f62b6d9e8815acbf7cd2e476ea353743570610737b752
Status: Downloaded newer image for hello-world:latest
# 下载完成后再运行

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常用命令

帮助命令

docker version

[root@localhost ~]# docker version
Client: Docker Engine - Community
 Version:           19.03.7
 API version:       1.40
 Go version:        go1.12.17
 Git commit:        7141c199a2
 Built:             Wed Mar  4 01:24:10 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.7
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.17
  Git commit:       7141c199a2
  Built:            Wed Mar  4 01:22:45 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

docker info

docker --help

可以查看docker命令的参数。

[root@localhost ~]# docker --help

Usage:	docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set
                           with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container`s changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container`s filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container`s filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.

镜像命令

列出:docker images

列出本地主机的镜像

[root@localhost ~]# docker images
#镜像的仓库源        镜像标签                镜像ID            创建时间            镜像大小
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        14 months ago       1.84kB

同一仓库源可以有多个TAG,代表这个仓库源的不同个版本,可以使用 REPOSITORY:TAG 来定义不同的镜像。
如果不指定镜像的标签版本,则默认使用hello-world:latest镜像

命令帮助

[root@localhost ~]# docker images  --help

Usage:	docker images [OPTIONS] [REPOSITORY[:TAG]]

List images

Options:
  -a, --all             Show all images (default hides intermediate images)  # 显示所有镜像,不要-a默认隐藏中间镜像层,因为镜像是分层的
      --digests         Show digests  # 显示摘要
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print images using a Go template
      --no-trunc        Don`t truncate output  # 显示完整的镜像信息,ID会很长
  -q, --quiet           Only show numeric IDs  # 只显示镜像的ID

# 可以多个选项公用,例如docker images -qa,显示所有镜像的ID

搜索:docker search 镜像名

[root@localhost ~]# docker search nginx
#名称                                    描述                                     在hub上的star数         官方版               自动构建的 
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                              Official build of Nginx.                        12758               [OK]                
jwilder/nginx-proxy                Automated Nginx reverse proxy for docker con…   1749                                    [OK]
richarvey/nginx-php-fpm            Container running Nginx + PHP-FPM capable of…   758                                     [OK]

命令帮助

[root@localhost ~]# docker search --help

Usage:	docker search [OPTIONS] TERM

Search the Docker Hub for images

Options:
  -f, --filter filter   Filter output based on conditions provided  # 根据提供的条件过滤输出
      --format string   Pretty-print search using a Go template  # 搜索时使用Go模板进行漂亮的打印
      --limit int       Max number of search results (default 25)  # 最多搜寻结果数目(预设25个)
      --no-trunc        Don`t truncate output  # 不截断输出,描述完整显示

# stars数量大于10000的列表
[root@localhost ~]# docker search --filter=stars=10000 nginx
NAME                DESCRIPTION                STARS               OFFICIAL            AUTOMATED
nginx               Official build of Nginx.   12758               [OK]    
# 只显示官方版
[root@localhost ~]# docker search --filter=is-official=true nginx
NAME                DESCRIPTION                STARS               OFFICIAL            AUTOMATED
nginx               Official build of Nginx.   12758               [OK]                
# 只显示自动构建的
[root@localhost ~]# docker search --filter=is-automated=true nginx
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
jwilder/nginx-proxy                Automated Nginx reverse proxy for docker con…   1749                                    [OK]

拉取:docker pull 镜像名[:标签]

[root@localhost ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
68ced04f60ab: Pull complete 
28252775b295: Pull complete 
a616aa3b0bf2: Pull complete 
Digest: sha256:2539d4344dd18e1df02be842ffc435f8e1f699cfc55516e2cf2cb16b7a9aea0b
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              6678c7c2e56c        40 hours ago        127MB
hello-world         latest              fce289e99eb9        14 months ago       1.84kB

删除:docker rmi 镜像名[:标签]

删除本地镜像,可以为镜像名,也可以镜像ID,加上-f选项表示强制删除

# 删除镜像,如果运行的容器正在使用这个镜像需要强制删除
[root@localhost ~]# docker rmi hello-world
Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container 6422bf65891a is using its referenced image fce289e99eb9
# 添加-f选项强制删除镜像
[root@localhost ~]# docker rmi -f hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:fc6a51919cfeb2e6763f62b6d9e8815acbf7cd2e476ea353743570610737b752
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              6678c7c2e56c        40 hours ago        127MB

删除多个镜像

[root@localhost ~]# docker rmi hello-world nginx

删除所有镜像

[root@localhost ~]# docker images -qa
6678c7c2e56c
fce289e99eb9
[root@localhost ~]# $(docker images -qa)
-bash: 6678c7c2e56c: 未找到命令
[root@localhost ~]# echo $(docker images -qa)
6678c7c2e56c fce289e99eb9
# 批量删除所有镜像
[root@localhost ~]# docker rmi $(docker images -qa)

容器命令

有镜像才能创建容器

[root@localhost ~]# docker pull centos
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              470671670cac        7 weeks ago         237MB

运行:docker run 镜像名[镜像ID]

常用选项

  • --name:为容器指定一个名称;
  • -d:后台运行容器,并返回容器的ID,即启动守护式容器;
  • -i:以交互模式运行容器,通常与-t一起使用
  • -t:为容器重新分配一个伪输入终端,通常与-i一起使用;
  • -P:随机端口映射docker run -it -P nginx随机分配端口0.0.0.0:32768->80/tcp
  • -p:指定端口映射,有以下格式:
    • ip:宿主机端口:容器端口
    • ip::容器端口
    • 宿主机端口:容器端口docker run -it -p 8000:80 nginx,外部通过8000端口访问容器内部80端口。
    • 容器端口

更多内容可以使用[root@localhost ~]# docker run --help获取

前台运行容器

[root@localhost ~]# docker run -it centos
# 以centos生成新的对象:02983b4225c6(容器ID)
# 然后就会进入容器的终端
[root@02983b4225c6 /]# pwd
/
[root@02983b4225c6 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

-p 端口映射

-p 外部端口:内部端口映射端口

# 一个窗口启动nginx,将容器中的80端口映射到外部8080上
[root@localhost ~]# docker run -it -p 8080:80 nginx

# 另一个窗口访问8080端口
[root@localhost ~]# curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
     
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

# 容器会显示以下日志
172.17.0.1 - - [09/Mar/2020:08:05:33 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

后台运行容器

[root@localhost ~]# docker run -d centos
9c950523ef0507a33bddd5182af726b886dde063a0ede403d96b66ad45f1c8dc
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
# 使用-d运行的容器,运行后就退出了
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
9c950523ef05        centos              "/bin/bash"         17 seconds ago      Exited (0) 16 seconds ago                       gallant_sanderson

Docker容器后台运行,就必须有一个前台进程。容器运行的命令如果不是那些一直挂起的命令(比如:top、tail),就是会自动退出的。
这是Docker的机制问题,例如web容器nginx,正常情况下,配置启动服务只需要启动相应的service即可service nginx start,但是这样,nginx为后台进程模式运行,就导致Docker前台没有运行的应用,这样的容器后台启动后,会立即退出,因为它觉得自己没有事可做了,所以最佳的解决方案是,将要运行的程序以前台进程的形式运行

所以让其程序保持前台运行

[root@localhost ~]# docker run -d centos /bin/bash -c "while true;do echo hello world; sleep 5;done"
90c18302fe0a4d64c615cfb0813e9d498dec89bdb084c1dc42340a8f6a576f31
# 可以看到这个后台运行的容器为Up的
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
90c18302fe0a        centos              "/bin/bash -c 'while…"   4 seconds ago       Up 3 seconds                            tender_engelbart
# 可以看到该容器的日志
[root@localhost ~]# docker logs 90c18302fe0a
hello world

退出:exit,离开Ctrl+P+Q

-it运行容器后可以通过输入exit命令回车退出当前容器,返回到宿主系统。

# 这就给新建的容器指定一个别名,即docker ps中NAMES列显示该名称
[root@localhost ~]# docker run -it --name ctos centos

[root@02983b4225c6 /]# exit
exit

在容器中按 Ctrl+P+Q 暂时离开容器,而不停止容器

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7b59830862d4        centos              "/bin/bash"         4 minutes ago       Up 4 minutes                            ctos

可以看到STATUSUp,表示容器在后台运行着

列出:docker ps

查看docker中运行的容器,新开一个终端,查看运行中的容器

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
02983b4225c6        centos              "/bin/bash"         3 minutes ago       Up 3 minutes                            suspicious_proskuriakova

常用选项

  • -a:累出当前所有正在运行的容器和历史上运行过的容器
  • -l:显示最近创建的容器
  • -n:显示最近n个创建的容器
  • -q:静默模式,只显示容器编号CONTAINER ID列表
  • --no-trunc:不截断输出

可以通过[root@localhost ~]# docker ps --help查看该命令的所有选项。

启动:docker start 容器ID[容器名]

start启动退出的容器会保持容器之前的配置。

02983b4225c6        centos              "/bin/bash"         2 hours ago         Exited (0) 13 minutes ago                       suspicious_proskuriakova

对于状态为Exited的容器,如果想重新进入,可以指定其ID02983b4225c6或容器名称

[root@localhost ~]# docker start 02983b4225c6
02983b4225c6
[root@localhost ~]# docker ps -a | grep 02983b4225c6
02983b4225c6        centos              "/bin/bash"         2 hours ago         Up 17 seconds                                 suspicious_proskuriakova

重启:docker restart 容器ID[容器名]

对于运行中的容器,可以通过restart进行重启

[root@localhost ~]# docker ps -a | grep -E 'ctos|STATUS'
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS               NAMES
7b59830862d4        centos              "/bin/bash"         13 minutes ago      Up 13 minutes                                 ctos
# 指定容器名进行重启
[root@localhost ~]# docker restart ctos
ctos
[root@localhost ~]# docker ps -a | grep -E 'ctos|STATUS'
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS               NAMES
7b59830862d4        centos              "/bin/bash"         13 minutes ago      Up 3 seconds                                  ctos

可以看到重启成功后STATUSUp时间发生变化。

停止:docker stop 容器ID[容器名]

stop类似于电脑正常关机

强制停止:docker kill 容器ID[容器名]

kill类似于电脑拔电源

删除:docker rm 容器ID[容器名]

删除已停止的容器

[root@localhost ~]# docker ps -a | grep -E 'STATUS|Exited'
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS               NAMES
6422bf65891a        hello-world         "/hello"            46 hours ago        Exited (0) 46 hours ago                       xenodochial_shtern
[root@localhost ~]# docker rm 6422bf65891a
6422bf65891a
[root@localhost ~]# docker ps -a | grep -E 'STATUS|Exited'
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

docker rm -f 容器ID[容器名]强制删除,可以强制删除正在运行的容器。

一次性删除多个容器

docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm

日志:docker logs 容器ID

docker logs -f -t --tail 10 容器ID

-t:加入时间戳
-f:跟随最新的日志打印
--tail 数字:显示最后多少条

# 查看容器的运行日志
[root@localhost ~]# docker logs 90c18302fe0a
# 查看日志前面会添加上时间,例如2020-03-08T09:22:28.787068489Z 
[root@localhost ~]# docker logs -t 90c18302fe0a
# 实时日志输出
[root@localhost ~]# docker logs -t -f 90c18302fe0a
# 显示最后多少条
[root@localhost ~]# docker logs -t -f --tail 3 90c18302fe0a

进程:docker top 容器ID

查看指定容器运行的进程

[root@localhost ~]# docker top 90c18302fe0a
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                9697                9681                0                   17:21               ?                   00:00:00            /bin/bash -c while true;do echo hello world; sleep 5;done
root                9860                9697                0                   17:27               ?                   00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5

细节:docker inspect 容器ID

查看容器内部细节,以键值对的形式看到ID、创建时间、路径、参数、状态等详细信息。

[root@localhost ~]# docker inspect 90c18302fe0a

进入:docker attach [exec -t 命令] 容器ID

进入正在运行中的容器并以命令行交换:

  • docker exec -t 容器ID bash脚本:在容器中打开新的终端,并且可以启动新的进程。
  • docker attach 容器ID等效docker exec -it 容器ID /bin/bash:重新进入,直接进入容器启动命令的终端,不会启动新的进程。
# 前台运行容器后,按Ctrl+P+Q返回到宿主机
[root@localhost ~]# docker run -it centos
[root@12396f0fe5e7 /]# [root@localhost ~]# 
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
12396f0fe5e7        centos              "/bin/bash"         11 seconds ago      Up 11 seconds                           amazing_ishizaka

# 要重新进入容器
[root@localhost ~]# docker attach 12396f0fe5e7
[root@12396f0fe5e7 /]# ls /tmp/
ks-script-_srt3u3c  ks-script-gpqu_kuo
# 等效与
[root@localhost ~]# docker exec -it 12396f0fe5e7 /bin/bash
[root@12396f0fe5e7 /]# ls /tmp/
ks-script-_srt3u3c  ks-script-gpqu_kuo


# 再按Ctrl+P+Q返回,这个容器没有退出
[root@localhost ~]# docker exec -t 12396f0fe5e7 ls /tmp/
ks-script-_srt3u3c  ks-script-gpqu_kuo
# 直接在宿主机中显示容器中的执行结果

拷贝:docker cp 容器ID:容器内路径 目的主机路径

容器内的文件拷贝到宿主机上

[root@localhost ~]# docker cp 12396f0fe5e7:/var/log/dnf.log /root/
[root@localhost ~]# ls /root/ | grep log
dnf.log

提交镜像:docker commit

提交容器副本使之成为一个新的镜像。
docker commit -m="提交的描述信息" -a="作者" 容器ID [命名空间]要创建的目标镜像名[:标签名]

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
12396f0fe5e7        centos              "/bin/bash"         23 hours ago        Up 23 hours                             amazing_ishizaka
# 修改过的容器提交为新的镜像
[root@localhost ~]# docker commit -a="username" -m="new centos" 12396f0fe5e7 namespace/centos:0.2
sha256:1195bb59f2dd1dbf2542ef37545ea05cc972373e2227a5636afb3ff76ea4529e

# 查看新提交的镜像
[root@localhost ~]# docker images | grep -E 'TAG|centos'
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
namespace/centos    0.2                 1195bb59f2dd        2 minutes ago       300MB
centos              latest              470671670cac        7 weeks ago         237MB

# 运行自己创建的镜像,由于自己的镜像创建了标签不是latest,需要加上标签
[root@localhost ~]# docker run -it namespace/centos:0.2
[root@6c67e5e78506 /]# exit
exit

Docker容器数据卷

概念

Docker理念:

  • 将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但要对数据的要求希望是持久化的;
  • 容器之间希望有可能共享数据。

Docker容器产生的数据,如果不通过docker commit生成新的镜像,使数据作为镜像的一部分保存下来,那么容器删除后,数据就没有了。
而容器数据卷就是为了能保存数据。类似于Redis中的rdb和aof文件。

作用

卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但不属于联合文件系统,因此能够绕过Union Filre System提供一些用于持久存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生命周期,因此Docker不会在容器删除时删除其挂载的数据卷。

特点:

  • 数据卷可以在容器之间共享或重用数据;
  • 数据卷中的更改可以直接生效;
  • 数据卷中的更改不会包含在镜像的更新中;
  • 数据卷的生命周期一直持续到没有容器使用它为止;
  • 即容器数据的持久化,容器间继承和共享数据。

添加数据卷 -v 路径映射

容器内添加数据卷

直接命令添加

docker run -it -v /宿主机的绝对路径目录:/容器内目录 镜像名 :映射可读可写目录。

[root@localhost ~]# docker run -it -v /hostData:/dockerData centos
# 容器内
[root@2222a6d184c9 /]# ls | grep Data
dockerData
[root@2222a6d184c9 /]# touch /dockerData/1.py

# 宿主机内根目录
[root@localhost ~]# ls / | grep Data
hostData
[root@localhost ~]# ls /hostData/

# 查看该容器的细节
[root@localhost ~]# docker inspect 2222a6d184c9
            "Binds": [
                "/hostData:/dockerData"
            ],  # 主机路径为/hostData,容器对应路径为/dockerData
# ...            
        "Mounts": [
            {
     
                "Type": "bind",
                "Source": "/hostData",
                "Destination": "/dockerData",
                "Mode": "",
                "RW": true,  # 目录可读写
                "Propagation": "rprivate"
            }
        ],

可以看到-v创建目录映射后,会在宿主机和容器内都创建指定的路径,并实现数据共享。
容器停止或退出后,如果修改了宿主机中的数据,当容器再次start启动后,容器内数据保持一致。

docker run -it -v /宿主机的绝对路径目录:/容器内目录:ro 镜像名 :映射容器内只读目录,ro表示只读。

# 启动容器,容器内只读
[root@localhost ~]# docker run -it -v /hostData:/dockerData:ro centos
[root@9440e1cef6d4 /]# ls /dockerData/
1.py
# 在容器内删除文件,由于设置的ro,只读不允许删除
[root@9440e1cef6d4 /]# rm -f /dockerData/1.py 
rm: cannot remove '/dockerData/1.py': Read-only file system
# 容器内也不能创建文件
[root@9440e1cef6d4 /]# touch /dockerData/2.sh
touch: cannot touch '/dockerData/2.sh': Read-only file system

# 宿主机内创建文件
[root@localhost ~]# touch /hostData/2.sh
# 容器内可以直接查看
[root@9440e1cef6d4 /]# ls /dockerData/
1.py  2.sh

# 查看该容器的细节
[root@localhost ~]# docker inspect 9440e1cef6d4
            "Binds": [
                "/hostData:/dockerData:ro"
            ],  # 映射目录
# ...            
        "Mounts": [
            {
     
                "Type": "bind",
                "Source": "/hostData",
                "Destination": "/dockerData",
                "Mode": "ro",  # 设置为ro,表示只读,不允许写操作
                "RW": false,
                "Propagation": "rprivate"
            }
        ],

Dockerfile添加

Dockerfile:对镜像源码级的描述。

可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷。

VOLUME["/dataVolumeContainer1","/dataVolumeContainer2"],"/dataVolumeContainer3"]]

说明:
出于可移植和分享的考虑,用-v 主机目录:容器目录这种方式不能直接在Dockerfile中实现;
由于宿主机目录是依赖于特定宿主机的,并不能保证在所有的宿主机上都存在这样的特定目录。

可以查看 https://hub.docker.com/_/redis redis的Dockerfile,编写一个自己的,只涉及到VOLUME

[root@localhost ~]# vim Dockerfile

# 添加以下内容,即Dockerfile脚本
FROM centos
VOLUME ["/dataVolumeContainer1","dataVolumeContainer2"]
CMD echo "finished!"
CMD /bin/bash

FROM指定基础镜像。VOLUME指定在在容器内新建的容器卷,该镜像启动的容器会在容器中自动创建指定的目录。CMD指定运行命令。

使用docker build基于Dockerfile构建新的镜像

[root@localhost ~]# docker build -f ./Dockerfile -t username/centos .
Sending build context to Docker daemon  73.01MB
Step 1/4 : FROM centos
 ---> 470671670cac
Step 2/4 : VOLUME ["/dataVolumeContainer1","dataVolumeContainer2"]
 ---> Running in 802acfdb9c70
Removing intermediate container 802acfdb9c70
 ---> 56afc199843d
Step 3/4 : CMD echo "finished!"
 ---> Running in 3257a1985c98
Removing intermediate container 3257a1985c98
 ---> c42d4cf661b0
Step 4/4 : CMD /bin/bash
 ---> Running in 826e6bf4540d
Removing intermediate container 826e6bf4540d
 ---> e798b17c7ed0
Successfully built e798b17c7ed0
# 一层一层叠加构建最后的镜像
Successfully tagged username/centos:latest

# 查看构建的新镜像
[root@localhost ~]# docker images username/centos
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
username/centos     latest              e798b17c7ed0        4 minutes ago       237MB

-f:指定Dockerfile文件位置
-t:构建的镜像仓库名
.:表示当前目录,是在指定 上下文路径

运行容器

[root@localhost ~]# docker run -it username/centos
# 自动创建了改目录
[root@b7a12418ff2c /]# ls | grep data 
dataVolumeContainer1
dataVolumeContainer2

# 查看容器挂载信息
[root@localhost ~]# docker inspect b7a12418ff2c

        "Mounts": [
            {
     
                "Type": "volume",
                "Name": "18d983de94e78375e1f3bc200043319520c0a7fea8f5931129a12298df1d0674",
                "Source": "/var/lib/docker/volumes/18d983de94e78375e1f3bc200043319520c0a7fea8f5931129a12298df1d0674/_data",  # 宿主机目录
                "Destination": "/dataVolumeContainer1",  # 容器内目录
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
     
                "Type": "volume",
                "Name": "52e0c8b0d644a11a498e2dbc64abeb6b7fbc042507a1004247b4c2eb18578630",
                "Source": "/var/lib/docker/volumes/52e0c8b0d644a11a498e2dbc64abeb6b7fbc042507a1004247b4c2eb18578630/_data",
                "Destination": "dataVolumeContainer2",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
# ...
            "Volumes": {
     
                "/dataVolumeContainer1": {
     },
                "dataVolumeContainer2": {
     }
            },

# 可以在宿主机中创建文件,查看容器内是否存在
[root@localhost ~]# touch /var/lib/docker/volumes/18d983de94e78375e1f3bc200043319520c0a7fea8f5931129a12298df1d0674/_data/1.py
# 在容器内可以查看该目录文件
[root@b7a12418ff2c /]# ls /dataVolumeContainer1
1.py

也就是使用VOLUME也实现了宿主机与容器内数据共享。

privileged=true

另外假如Docker挂载主机目录Docker内访问出现cannot open directory:Permission denied,解决办法是,在挂载目录后多加一个--privileged=true参数即可。即docker run -it username/centos --privileged=true

数据卷容器:容器卷共享给另一容器

命名的容器挂载数据卷,其它同期通过挂载这个(父容器)实现数据共享,容器数据卷的容器,称之为数据卷容器。吧容器比喻为移动硬盘,移动硬盘上挂载移动硬盘,实现数据的传递依赖。

容器数据传递 --volumes-from

使用上面Dockerfile生成的镜像启动容器。

# 创建一个新的容器,指定明曾为ctos01,使用Dockerfile主要是用他的挂载数据卷功能
[root@localhost ~]# docker run -it --name ctos01 username/centos
[root@4343d5788088 /]# ls -l | grep data
drwxr-xr-x.   2 root root   6 Mar 10 04:11 dataVolumeContainer1
drwxr-xr-x.   2 root root   6 Mar 10 04:11 dataVolumeContainer2
# 在该ctos01容器内创建一个文件
[root@4343d5788088 /]# touch /dataVolumeContainer1/1.py
[root@4343d5788088 /]# ls /dataVolumeContainer1
1.py
# Ctrl+P+Q离开容器
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
4343d5788088        username/centos     "/bin/sh -c /bin/bash"   2 minutes ago       Up 2 minutes                            ctos01

# 再启动另一个容器取名为ctos02,数据卷继承于ctos01
[root@localhost ~]# docker run -it --name ctos02 --volumes-from ctos01 username/centos
[root@0ea7362e24c7 /]# ls -l | grep data
drwxr-xr-x.   2 root root  18 Mar 10 04:12 dataVolumeContainer1
drwxr-xr-x.   2 root root   6 Mar 10 04:11 dataVolumeContainer2
[root@0ea7362e24c7 /]# ls /dataVolumeContainer1/
1.py

# 如果在容器2内新建一个文件,那么在容器1中也同样有
[root@0ea7362e24c7 /]# touch dataVolumeContainer2/2.py
[root@0ea7362e24c7 /]# [root@localhost ~]# 
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
0ea7362e24c7        username/centos     "/bin/sh -c /bin/bash"   5 minutes ago       Up 5 minutes                            ctos02
4343d5788088        username/centos     "/bin/sh -c /bin/bash"   9 minutes ago       Up 9 minutes                            ctos01
[root@localhost ~]# docker attach 4343d5788088
[root@4343d5788088 /]# ls /dataVolumeContainer2/
2.py
  • 子容器创建时可以通过--volumes-from 父容器名来继承父容器的数据卷;
  • 如果子容器继承了父容器的数据卷,即使父容器被删除了,子容器内数据依旧存在;
  • 继承父容器,即子容器都有相同的宿主机对应目录,即不管创建多少子容器,只要通过--volumes-from指定,则拥有相同的映射目录,这一点可以查看各个容器的inspect信息,MountsSource宿主机路径一样;
  • 容器之间配置信息的传递,数据卷的生命周期一直吃需要没有容器使用它为止。

Dockerfile

概念

Dockerfile是用来构建Docker镜像的构建文件,是一系列命令和参数构成的脚本。

构建三步骤:编写Dockerfile文件 -> docker build -> docker run

参考centos的Dockerfile,访问 https://hub.docker.com/_/centos 即可,可以上dockerhub上搜索

# 以下即为最新的centos8的Dockerfile
FROM scratch
ADD CentOS-8-Container-8.1.1911-20200113.3-layer.x86_64.tar.xz  /

LABEL org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20200114" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-01-14 00:00:00-08:00"

CMD ["/bin/bash"]

基础知识

  • 每条保留字指令都必须为大写字母后面要跟随至少一个参数,不能没有参数;
  • 指定按照从上到下,顺序执行;
  • #表示注释;
  • 每条指令都会创建一个新的镜像层,并对镜像进行提交

执行Dockerfile大致流程

  1. docker从基础镜像运行一个容器;
  2. 执行一条指令并对容器作出修改;
  3. 执行类似docker commit的操作提交一个新的镜像层;
  4. 再基于刚提交的镜像运行一个新容器;
  5. 执行Dockerfile中的下一条指令,提交,运行,直到所有指令都执行完成。

从应用软件的角度看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个阶段:

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态

Dockerfile面向开发,Docker镜像称为交付标准,Docker容器则涉及到部署与运维。

体系结构,保留字指令

FROM

基础镜像,当前新镜像是基于哪个镜像的。

MAINTAINER

镜像维护者的姓名和邮箱地址

RUN

容器构建时需要运行的命令

EXPOSE

当前容器对外暴露的端口号

WORKDIR

指定在创建容器后,终端默认登录进来的工作目录

ENV

用来在构建镜像过程中设置环境变量

ENV MY_PATH /data这个环境变量可以在后续的任何RUN指令中使用,这就像在命令前面指定了环境变量前缀一样,也可以在其它指令中直接使用这些环境变量,比如WORKDIR $MY_PATH,那么用户登录后就会切换到/data目录。

ADD

将宿主机目录下的文件拷贝到镜像,且ADD命令会自动处理URL和解压tar压缩包

COPY

类似ADD,拷贝文件和目录到镜像中。
将从构建上下文目录中<源路径>的 文件/目录 复制到新的一层镜像内的<目标路径>位置。

VOLUME

容器数据卷,用于数据保存和持久化工作。

CMD

指定一个容器启动时要运行的命令。
Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换。

ENTRYPOINT

指定一个容器启动时要运行的命令。
ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数。人为在docker run添加参数会被追加,不会覆盖。

ONBUILD

当构建一个被继承的Dockerfile时运行命令,父镜像在被子镜像继承后,父镜像的ONBUILD被触发。

构建:docker build

docker build -f /oath/Dockerfilexx -t [命名空间/]新镜像名[:TAG] .
如果Dockerfile文件的名字为Dockerfile,可以不要-f,即docker build -t [命名空间/]新镜像名[:TAG] .

构建时默认会使用缓存,如果不需要加上--no-cache

案例

Base镜像(FROM scratch),Dockerhub中绝大多数镜像都是通过在base镜像中安装和配置需要的软件构建出来的。

自定义镜像centos

编写Dockerfile文件

[root@localhost ~]# vim NewCentOSDockerfile
[root@localhost ~]# cat NewCentOSDockerfile 
FROM centos
MAINTAINER name<[email protected]>

ENV myPath /usr/local
WORKDIR $myPath
CMD echo $myPath

RUN yum install vim -y

CMD echo "success!"

CMD /bin/bash

构建镜像

[root@localhost ~]# docker build -f ./NewCentOSDockerfile -t mycentos:1.2 .
Sending build context to Docker daemon  73.01MB
Error response from daemon: Dockerfile parse error line 6: unknown instruction: ECHO
[root@localhost ~]# vim NewCentOSDockerfile
[root@localhost ~]# vim NewCentOSDockerfile
[root@localhost ~]# docker build -f ./NewCentOSDockerfile -t mycentos:1.2 .
Sending build context to Docker daemon  73.01MB
Step 1/8 : FROM centos
 ---> 470671670cac
Step 2/8 : MAINTAINER name<[email protected]>
 ---> Running in 52d2b6895fdc
Removing intermediate container 52d2b6895fdc
 ---> 45d8217d2eb8
Step 3/8 : ENV myPath /usr/local
 ---> Running in 230bb81d9fab
Removing intermediate container 230bb81d9fab
 ---> 1a457ebf46b4
Step 4/8 : WORKDIR $myPath
 ---> Running in 00fd62387ffd
Removing intermediate container 00fd62387ffd
 ---> 16ac794f9fca
Step 5/8 : CMD echo $myPath
 ---> Running in 3e38360ba88e
Removing intermediate container 3e38360ba88e
 ---> 86bdd475d6c2
Step 6/8 : RUN yum install vim -y
 ---> Running in a6c768596f78
CentOS-8 - AppStream                            2.1 MB/s | 6.5 MB     00:03    
CentOS-8 - Base                                 1.1 MB/s | 5.0 MB     00:04    
CentOS-8 - Extras                                82  B/s | 2.1 kB     00:26    
Dependencies resolved.
# 安装vim步骤 
Complete!
Removing intermediate container a6c768596f78
 ---> 02b0c69b9d48
Step 7/8 : CMD echo "success!"
 ---> Running in 582dfaf2fb2b
Removing intermediate container 582dfaf2fb2b
 ---> 18a387f8de7d
Step 8/8 : CMD /bin/bash
 ---> Running in 66733aa5f7c3
Removing intermediate container 66733aa5f7c3
 ---> 9c093775a751
Successfully built 9c093775a751
Successfully tagged mycentos:1.2

可以看到生成的新镜像和原centos对比

[root@localhost ~]# docker images mycentos
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mycentos            1.2                 9c093775a751        7 minutes ago       300MB
[root@localhost ~]# docker images centos
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              470671670cac        7 weeks ago         237MB

运行容器

[root@localhost ~]# docker run -it mycentos:1.2
# 运行容器可以看到,登录的位置即为Dockerfile中WORKDIR指定的
[root@3802d2b22c0d local]# pwd
/usr/local
# 由于Dockerfile中安装了vim,则新的容器就支持vim编辑器了
[root@3802d2b22c0d local]# vim

查看镜像修改历史 docker history

[root@localhost ~]# docker history mycentos:1.2
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
9c093775a751        14 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B                  
18a387f8de7d        14 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
02b0c69b9d48        14 minutes ago      /bin/sh -c yum install vim -y                   63.2MB              
86bdd475d6c2        15 minutes ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
16ac794f9fca        15 minutes ago      /bin/sh -c #(nop) WORKDIR /usr/local            0B                  
1a457ebf46b4        15 minutes ago      /bin/sh -c #(nop)  ENV myPath=/usr/local        0B                  
45d8217d2eb8        15 minutes ago      /bin/sh -c #(nop)  MAINTAINER name
470671670cac        7 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           7 weeks ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           7 weeks ago         /bin/sh -c #(nop) ADD file:aa54047c80ba30064…   237MB               

从下往上一层一层叠加的镜像。

CMD对比ENTRYPOINT

CMD指令

对于centos的镜像的Dockerfile文件,最后是CMD ["/bin/bash"]

# 创建一个新的Dockerfile
[root@localhost ~]# vim Dockerfile1
[root@localhost ~]# cat Dockerfile1 
FROM centos

CMD ["ls"]

# 构建新的镜像
[root@localhost ~]# docker build -f ./Dockerfile1 -t xx/centos1 .
Sending build context to Docker daemon  73.01MB
Step 1/2 : FROM centos
 ---> 470671670cac
Step 2/2 : CMD ["ls"]
 ---> Running in 05ebaa6aea53
Removing intermediate container 05ebaa6aea53
 ---> d21d177ce3cc
Successfully built d21d177ce3cc
Successfully tagged xx/centos1:latest

# 查看新生成的镜像
[root@localhost ~]# docker images xx/centos1
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
xx/centos1          latest              d21d177ce3cc        About a minute ago   237MB

那么启动该镜像默认使用ls显示根目录的信息

# 使用该镜像启动新的容器
[root@localhost ~]# docker run -it xx/centos1
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr

# 如果还想扩展其参数,例如ls -l,那么运行时就会报错,因为他是替换原DockerfileCMD 命令
[root@localhost ~]# docker run -it xx/centos1 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.

# 要想实现该功能,需要完整书写ls -l命令
[root@localhost ~]# docker run -it xx/centos1 ls -l
total 0
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 360 Mar 10 13:02 dev
drwxr-xr-x.   1 root root  66 Mar 10 13:02 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
lrwxrwxrwx.   1 root root   7 May 11  2019 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 May 11  2019 lib64 -> usr/lib64
drwx------.   2 root root   6 Jan 13 21:48 lost+found
drwxr-xr-x.   2 root root   6 May 11  2019 media
drwxr-xr-x.   2 root root   6 May 11  2019 mnt
drwxr-xr-x.   2 root root   6 May 11  2019 opt
dr-xr-xr-x. 135 root root   0 Mar 10 13:02 proc
dr-xr-x---.   2 root root 162 Jan 13 21:49 root
drwxr-xr-x.  11 root root 163 Jan 13 21:49 run
lrwxrwxrwx.   1 root root   8 May 11  2019 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 May 11  2019 srv
dr-xr-xr-x.  13 root root   0 Mar  5 10:02 sys
drwxrwxrwt.   7 root root 145 Jan 13 21:49 tmp
drwxr-xr-x.  12 root root 144 Jan 13 21:49 usr
drwxr-xr-x.  20 root root 262 Jan 13 21:49 var

Dockerfile中最后一个CMD指令在启动容器时不加任何参数情况下生效,如果docker run后添加参数,那么CMD会被参数替换,也就是Dockerfile中的最后一个CMD无效了。
例如Dockerfile中是CMD ["ls"],如果使用docker run 镜像 ls -l,则会替换原来的命令组合CMD ["ls","-l"]

ENTRYPOINT指令

# 创建一个新的Dockerfile
[root@localhost ~]# vim Dockerfile2
[root@localhost ~]# cat Dockerfile2
FROM centos

ENTRYPOINT ["ls"]

# 构建新的镜像
[root@localhost ~]# docker build -f ./Dockerfile2 -t xx/centos2 .
Sending build context to Docker daemon  73.01MB
Step 1/2 : FROM centos
 ---> 470671670cac
Step 2/2 : ENTRYPOINT ["ls"]
 ---> Running in 43ad265872ea
Removing intermediate container 43ad265872ea
 ---> da5ea4042a02
Successfully built da5ea4042a02
Successfully tagged xx/centos2:latest

# 使用该镜像启动容器,默认会执行ls命令
[root@localhost ~]# docker run -it xx/centos2
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr

# 如果run后面添加参数,例如添加-l,就相当于把 ENTRYPOINT ["ls"] 变为 ENTRYPOINT ["ls","-l"],即执行 ls -l 命令了
[root@localhost ~]# docker run -it xx/centos2 -l
total 0
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 360 Mar 10 13:08 dev
drwxr-xr-x.   1 root root  66 Mar 10 13:08 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
lrwxrwxrwx.   1 root root   7 May 11  2019 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 May 11  2019 lib64 -> usr/lib64
drwx------.   2 root root   6 Jan 13 21:48 lost+found
drwxr-xr-x.   2 root root   6 May 11  2019 media
drwxr-xr-x.   2 root root   6 May 11  2019 mnt
drwxr-xr-x.   2 root root   6 May 11  2019 opt
dr-xr-xr-x. 135 root root   0 Mar 10 13:08 proc
dr-xr-x---.   2 root root 162 Jan 13 21:49 root
drwxr-xr-x.  11 root root 163 Jan 13 21:49 run
lrwxrwxrwx.   1 root root   8 May 11  2019 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 May 11  2019 srv
dr-xr-xr-x.  13 root root   0 Mar  5 10:02 sys
drwxrwxrwt.   7 root root 145 Jan 13 21:49 tmp
drwxr-xr-x.  12 root root 144 Jan 13 21:49 usr
drwxr-xr-x.  20 root root 262 Jan 13 21:49 var

docker run ***之后的参数,会被当作参数传递给ENTRYPOINT,形成新的命令组合。
例如Dockerfile中是ENTRYPOINT ["ls"],如果使用docker run 镜像 -l,则形成新的组合为ENTRYPOINT ["ls","-l"]

ONBUILD指令

子镜像构建时,触发父镜像的ONBUILD指令

# 创建父镜像的Dockerfile
[root@localhost ~]# vim Dockerfile3
[root@localhost ~]# cat Dockerfile3
FROM centos

ONBUILD RUN echo "父镜像被继承"

# 构建父镜像
[root@localhost ~]# docker build -f ./Dockerfile3 -t xx/centos3 .
Sending build context to Docker daemon  73.01MB
Step 1/2 : FROM centos
 ---> 470671670cac
Step 2/2 : ONBUILD RUN echo "父镜像被继承"
 ---> Running in 69744e0d9c78
Removing intermediate container 69744e0d9c78
 ---> 96719c852415
Successfully built 96719c852415
Successfully tagged xx/centos3:latest


# 创建子镜像的Dockerfile
[root@localhost ~]# vim Dockerfile4
[root@localhost ~]# cat Dockerfile4
FROM xx/centos3
CMD echo "子镜像继承centos3父镜像"

# 构建子镜像
[root@localhost ~]# docker build -f ./Dockerfile4 -t xx/centos4 .
Sending build context to Docker daemon  73.01MB
Step 1/2 : FROM xx/centos3
# Executing 1 build trigger  # 执行一个构建触发器
 ---> Running in 2a4a53e3bfda
父镜像被继承  # 并执行触发器中的内容
Removing intermediate container 2a4a53e3bfda
 ---> 3497155cb295
Step 2/2 : CMD echo "子镜像继承centos3父镜像"
 ---> Running in 6f36286e630a
Removing intermediate container 6f36286e630a
 ---> 68641db9fdfd
Successfully built 68641db9fdfd
Successfully tagged xx/centos4:latest

基于centos的tomcat自定义

准备需要的文件

# 创建一个文件夹,主要是放构建Docker镜像存放的文件
[root@localhost ~]# mkdir mytomcat9
[root@localhost ~]# cd mytomcat9/
# 这个文件仅作为COPY功能的讲解
[root@localhost mytomcat9]# touch test.txt
# 准备要Linux上用的jdk和tomcat
[root@localhost mytomcat9]# ls -l
总用量 198044
-rw-r--r--. 1 root root  11042076 3月  10 22:48 apache-tomcat-9.0.31.tar.gz
-rw-r--r--. 1 root root 191753373 3月  10 22:48 jdk-8u191-linux-x64.tar.gz
-rw-r--r--. 1 root root         0 3月  10 22:38 test.txt

创建Dockerfile文件

# 创建Dockerfile文件
[root@localhost mytomcat9]# vim Dockerfile 
[root@localhost mytomcat9]# cat Dockerfile 
# ---------Dockerfile 内容开始---------
FROM centos
MAINTAINER user<[email protected]>

# 把宿主机当前上下文的test.txt文件拷贝到容器/usr/local/路径下
COPY test.txt /usr/local/docker_ts.txt

# 把java与tomcat添加到容器中,ADD文件拷贝到镜像,且自动处理tar
ADD apache-tomcat-9.0.31.tar.gz /usr/local
ADD jdk-8u191-linux-x64.tar.gz /usr/local

# 安装vim编辑器,RUN表示容器构建时需要运行命令
RUN yum install vim -y

# 设置登录路径
ENV MYPATH /usr/local
WORKDIR $MYPATH

# 配置java与tomcat环境变量
# 解压文件:jdk-8u191-linux-x64.tar.gz\jdk-8u191-linux-x64.tar\jdk1.8.0_191
ENV JAVA_HOME $MYPATH/jdk1.8.0_191
# 解压文件:apache-tomcat-9.0.31.tar.gz\apache-tomcat-9.0.31.tar\apache-tomcat-9.0.31
ENV CATALINA_HOME $MYPATH/apache-tomcat-9.0.31
ENV CATALINA_BASE $MYPATH/apache-tomcat-9.0.31

ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

# 容器运行时监听的端口
EXPOSE 8080

# 启动tomcat
# 可以将tail -f修改为tail -F,如果是-f,知不道文件就直接退出了,-F保持等待状态,如果生成了该文件,则读取该文件
CMD $TOMCAT_HOME/bin/startup.sh && tail -f $TOMCAT_HOME/bin/logs/catalina.out
# ---------Dockerfile 内容结束---------

构建镜像

# 构建镜像,由于这儿Dockerfile文件名字就是Dockerfile,就不需要-t指定Dockerfile的位置了。
Sending build context to Docker daemon  202.8MB
Step 1/15 : FROM centos
 ---> 470671670cac
Step 2/15 : MAINTAINER user<[email protected]>
 ---> Running in 1b12d8e8ddb5
Removing intermediate container 1b12d8e8ddb5
 ---> 2e9788470b9e
Step 3/15 : COPY test.txt /usr/local/docker_ts.txt
 ---> 1383ea131647
Step 4/15 : ADD apache-tomcat-9.0.31.tar.gz /usr/local
 ---> be1bc068b64b
Step 5/15 : ADD jdk-8u191-linux-x64.tar.gz /usr/local
 ---> 8b368c4df92a
Step 6/15 : RUN yum install vim -y
 ---> Running in d81f55b59bf5
# 安装vim过程
Complete!
Removing intermediate container d81f55b59bf5
 ---> c4d4aa75b738
Step 7/15 : ENV MYPATH /usr/local
 ---> Running in 6e3e187123b0
Removing intermediate container 6e3e187123b0
 ---> 5e7df3381148
Step 8/15 : WORKDIR $MYPATH
 ---> Running in e46a5f8e5923
Removing intermediate container e46a5f8e5923
 ---> b6d994641f70
Step 9/15 : ENV JAVA_HOME $MYPATH/jdk1.8.0_191
 ---> Running in fbc8d90ec7dc
Removing intermediate container fbc8d90ec7dc
 ---> a7f5817c6d4a
Step 10/15 : ENV CATALINA_HOME $MYPATH/apache-tomcat-9.0.31
 ---> Running in 8f57522b9746
Removing intermediate container 8f57522b9746
 ---> a7f0c37e8e52
Step 11/15 : ENV CATALINA_BASE $MYPATH/apache-tomcat-9.0.31
 ---> Running in 7bd62a5e63e6
Removing intermediate container 7bd62a5e63e6
 ---> ba9bb1a1c673
Step 12/15 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
 ---> Running in 328cc850b6ed
Removing intermediate container 328cc850b6ed
 ---> afef88932865
Step 13/15 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
 ---> Running in 20d65387be48
Removing intermediate container 20d65387be48
 ---> b690839100b7
Step 14/15 : EXPOSE 8080
 ---> Running in 271962a4a2ae
Removing intermediate container 271962a4a2ae
 ---> a01da27056e9
Step 15/15 : CMD $CATALINA_HOME/bin/startup.sh && tail -f $CATALINA_HOME/logs/catalina.out
 ---> Running in 67a4b5f746ff
Removing intermediate container 67a4b5f746ff
 ---> 88d770b804b0
Successfully built 88d770b804b0
Successfully tagged mytomcat9:latest

# 查看构建的镜像
[root@localhost mytomcat9]# docker images mytomcat9
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mytomcat9           latest              88d770b804b0        42 seconds ago      712MB

指定该镜像运行容器

映射端口-p 9090:8080
映射路径-v /mydocker/mytomcat9/test:/usr/local/apache-tomcat-9.0.31/webapps/test
映射路径-v /mydocker/mytomcat9/logs:/usr/local/apache-tomcat-9.0.31/logs
如果Docker容器内访问宿主机目录出现权限问题使用--privileged=true

[root@localhost mytomcat9]# docker run -d -p 9090:8080 --name mytc9 -v /mydocker/mytomcat9/test:/usr/local/apache-tomcat-9.0.31/webapps/test -v /mydocker/mytomcat9/logs:/usr/local/apache-tomcat-9.0.31/logs --privileged=true mytomcat9
df51a503bd2a8677ff72489faee89f11674f440a70bf460bab90d0e8ef747479

# 查看容器运行状态
[root@localhost mytomcat9]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
df51a503bd2a        mytomcat9           "/bin/sh -c '$CATALI…"   8 seconds ago       Up 7 seconds        0.0.0.0:9090->8080/tcp   mytc9
[root@localhost mytomcat9]# docker logs df51a503bd2a
Tomcat started.
11-Mar-2020 02:54:56.948 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name:   Apache Tomcat/9.0.31
11-Mar-2020 02:54:56.965 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Feb 5 2020 19:32:12 UTC
11-Mar-2020 02:54:56.965 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.31.0
11-Mar-2020 02:54:56.965 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Linux
11-Mar-2020 02:54:56.965 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            3.10.0-1062.4.1.el7.x86_64
11-Mar-2020 02:54:56.966 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          amd64
11-Mar-2020 02:54:56.966 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /usr/local/jdk1.8.0_191/jre
11-Mar-2020 02:54:56.966 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           1.8.0_191-b12
11-Mar-2020 02:54:56.966 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
11-Mar-2020 02:54:56.966 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         /usr/local/apache-tomcat-9.0.31
11-Mar-2020 02:54:56.966 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         /usr/local/apache-tomcat-9.0.31
# 很多日志输出

# 另外宿主机也自动创建了这两个目录
[root@localhost mytomcat9]# tree /mydocker/mytomcat9
/mydocker/mytomcat9
├── logs
│   ├── catalina.2020-03-11.log
│   ├── catalina.out
│   ├── host-manager.2020-03-11.log
│   ├── localhost.2020-03-11.log
│   ├── localhost_access_log.2020-03-11.txt
│   └── manager.2020-03-11.log
└── test


# 容器内/usr/local目录
[root@localhost mytomcat9]# docker exec -it df51a503bd2a ls
apache-tomcat-9.0.31	   docker_ts.txt  include	lib64	 share
apache-tomcat-9.0.31.logs  etc		  jdk1.8.0_191	libexec  src
bin			   games	  lib		sbin
[root@localhost mytomcat9]# docker exec -it df51a503bd2a java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

浏览器验证访问

# 防火墙允许端口
[root@localhost mytomcat9]# firewall-cmd --add-port 9090/tcp
success

然后浏览器访问 http://192.168.99.102:9090/ 就可以看到Apache Tomcat/9.0.31的页面了

发布测试的web服务

[root@localhost mytomcat9]# cd /mydocker/mytomcat9/test/
[root@localhost test]# mkdir WEB-INF
[root@localhost test]# cd WEB-INF/
[root@localhost WEB-INF]# vim web.xml
[root@localhost WEB-INF]# cat web.xml 
<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"  
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee   
        http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"  
    id="WebApp_ID" version="3.1">  
   
    <display-name>test</display-name>

</web-app>

[root@localhost WEB-INF]# cd ..
[root@localhost test]# vim a.jsp
[root@localhost test]# cat a.jsp 
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <h1>Welcome</h1>
    <%="front print"%>
    <br>
    <% System.out.println("backgroud print");  %>
  </body>
</html>

[root@localhost test]# tree
.
├── a.jsp
└── WEB-INF
    └── web.xml


# 编辑完后可以重启下重启
[root@localhost test]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
df51a503bd2a        mytomcat9           "/bin/sh -c '$CATALI…"   33 minutes ago      Up 7 minutes        0.0.0.0:9090->8080/tcp   mytc9
[root@localhost test]# docker restart df5

浏览器访问 http://192.168.99.102:9090/test/a.jsp
可以在查看容器的日志

[root@localhost test]# docker logs -t --tail 5 df5
2020-03-11T09:07:34.778003518Z backgroud print
2020-03-11T09:07:34.955522519Z backgroud print
2020-03-11T09:07:35.327600149Z backgroud print
2020-03-11T09:07:35.503474753Z backgroud print
2020-03-11T09:07:35.681386449Z backgroud print

映射的目录同样也可以查看到日志

[root@localhost test]# tail -n 5 /mydocker/mytomcat9/logs/catalina.out 
backgroud print
backgroud print
backgroud print
backgroud print
backgroud print

Docker常用安装

Docker安装mysql

拉取镜像

# 搜索镜像
[root@localhost ~]# docker search --limit 3  mysql
NAME                 DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                MySQL is a widely used, open-source relation…   9216                [OK]                
mysql/mysql-server   Optimized MySQL Server Docker images. Create…   681                                     [OK]
circleci/mysql       MySQL is a widely used, open-source relation…   19   

# 拉取镜像
[root@localhost ~]# docker pull mysql:5.7
# ...
Digest: sha256:f4a5f5be3d94b4f4d3aef00fbc276ce7c08e62f2e1f28867d930deb73a314c58
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

[root@localhost ~]# docker images mysql
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               5.7                 84164b03fa2e        6 days ago          456MB

启动容器

[root@localhost ~]# docker run -d -p 30306:3306 -v /mydocker/mysql/conf:/etc/mysql/conf.d -v /mydocker/mysql/logs:/logs -v /mydocker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=Pa$sW0rd --name mysql mysql:5.7
0b9b4a9166d8020f272d37c7ecff991eb0bf8c0e3fa722a6f657510db2ff4f97

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                                NAMES
0b9b4a9166d8        mysql:5.7           "docker-entrypoint.s…"   About a minute ago   Up About a minute   33060/tcp, 0.0.0.0:30306->3306/tcp   mysql

# 开启宿主机的防火墙端口
[root@localhost ~]# firewall-cmd --zone=public --add-port=30306/tcp
success
  • -p 30306:3306:端口映射,外部访问30306
  • -v /mydocker/mysql/conf:/etc/mysql/conf.d:mysql配置文件
  • -v /mydocker/mysql/logs:/logs:mysql日志文件
  • -v /mydocker/mysql/data:/var/lib/mysql:mysql数据文件
  • -e MYSQL_ROOT_PASSWORD=Pa$sW0rd:设置root的密码
  • --name mysql:运行服务名字

进入容器连接mysql

[root@localhost ~]# docker exec -it 0b9b4a9166d8 /bin/bash
root@0b9b4a9166d8:/# ps
bash: ps: command not found
root@0b9b4a9166d8:/# mysql -uroot -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

解决容器连接mysql 1045错误

解决步骤

root@0b9b4a9166d8:/# exit
exit
# 退出容器,在宿主机映射的mysql配置文件夹添加配置
[root@localhost ~]# vim /mydocker/mysql/conf/my.cnf
[root@localhost ~]# cat /mydocker/mysql/conf/my.cnf
# 添加以下内容
[mysqld]
skip-grant-tables

# 重启mysql容器
[root@localhost ~]# docker restart mysql
mysql
# 进入容器执行命令
[root@localhost ~]# docker exec -it mysql /bin/bash

# 由于是本地登录可以直接输入mysql连接
root@0b9b4a9166d8:/# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.29 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> quit;
Bye
# 测试帐密连接
root@0b9b4a9166d8:/# mysql -uroot -p
Enter password: # Pa$sW0rd
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.29 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> quit;
Bye

在宿主机中连接mysql

也可以使用宿主机的IP:mysql -h192.168.99.102 -P30306 -uroot -p

root@0b9b4a9166d8:/# exit
exit
[root@localhost ~]# mysql -h127.0.0.1 -P30306 -uroot -p
Enter password: # Pa$sW0rd
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.29 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> 

宿主机备份容器数据

[root@localhost ~]# docker exec -it mysql sh -c 'exec mysqldump --all-databases -uroot -pPa$sW0rd' > /mydocker/mysql/all-databases.sql

[root@localhost ~]# ls /mydocker/mysql/
all-databases.sql  conf  data  logs

Docker安装redis

拉取镜像

[root@localhost ~]# docker pull redis:5.0.7
[root@localhost ~]# docker images redis
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               5.0.7               7eed8df88d3b        13 days ago         98.2MB

启动容器

[root@localhost ~]# docker run -d -p 36079:6379 -v /mydocker/redis/data:/data --name redis redis:5.0.7 --appendonly yes
0634727a9e0a6ef82838965ee3349b8717bb1412053fa98c63de44669c978d31

[root@localhost ~]# docker ps | grep -E "IMAGE|redis"
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
0634727a9e0a        redis:5.0.7         "docker-entrypoint.s…"   8 seconds ago       Up 8 seconds        0.0.0.0:36079->6379/tcp   redis
  • -p 36079:6379:端口映射,外部36079访问
  • -v /mydocker/redis/data:/data:挂载容器/data目录
  • --appendonly yes:开启aof持久化

进入容器连接redis

[root@localhost ~]# docker exec -it redis /bin/bash
root@0634727a9e0a:/data# ls
appendonly.aof

# redis客户端连接
root@0634727a9e0a:/data# redis-cli
127.0.0.1:6379> set k1 1
OK
127.0.0.1:6379> get k1
"1"
127.0.0.1:6379> quit

root@0634727a9e0a:/data# exit
exit

宿主机连接redis

[root@localhost ~]# wget download.redis.io/releases/redis-5.0.7.tar.gz
[root@localhost ~]# tar -zxf redis-5.0.7.tar.gz 
[root@localhost ~]# cd redis-5.0.7
[root@localhost redis-5.0.7]# make && make install

# 测试连接容器内的redis
[root@localhost redis-5.0.7]# redis-cli -h 192.168.99.102 -p 36079
192.168.99.102:36079> get k1
"1"
192.168.99.102:36079> quit

自定义配置文件

由于在上面宿主机中安装redis来测试了,里面有原版的redis.conf文件

[root@localhost redis-5.0.7]# ls -l redis.conf
-rw-rw-r--. 1 root root 61797 11月 20 01:05 redis.conf

# 创建映射到宿主机的配置文件路径
[root@localhost redis-5.0.7]# mkdir -p /mydocker/redis/conf

# 复制配置文件
[root@localhost redis-5.0.7]# cp redis.conf /mydocker/redis/conf
[root@localhost redis-5.0.7]# cd

# 查看主要的配置
[root@localhost ~]# cat  /mydocker/redis/conf/redis.conf | grep -E "^bind |^daemonize |logfile |requirepass |appendonly "
bind 127.0.0.1
daemonize no
logfile ""
# requirepass foobared
appendonly no

# 使用sed修改配置
[root@localhost ~]# sed -i 's/bind 127.0.0.1/# bind 127.0.0.1/'  /mydocker/redis/conf/redis.conf
[root@localhost ~]# sed -i 's/# requirepass foobared/requirepass redis_pass/'  /mydocker/redis/conf/redis.conf

# 查看已修改过的配置
[root@localhost ~]# cat /mydocker/redis/conf/redis.conf | grep -E "^bind |^daemonize |logfile |requirepass |appendonly "
daemonize no
logfile ""
requirepass redis_pass
appendonly no

另外也可以通过--appendonly yes加参数形式启动容器。

redis.conf 中daemonize no。非后台模式,如果为yes会的导致 redis 无法启动,因为后台会导致docker无任务可做而退出。其他主要的就是bindrequirepasslogfileport

/mydocker/redis/conf目录下已经有了已修改过的redis.conf配置文件,使用它来启动容器,启动时给redis-server添加一些参数

# 因为之前启动过同名的,将其删除
[root@localhost ~]# docker rm -f redis

# 使用新配置启动容器
[root@localhost ~]# docker run -d -p 36079:6379 -v /mydocker/redis/data:/data -v /mydocker/redis/conf/redis.conf:/etc/redis/redis.conf --name redis redis:5.0.7 redis-server /etc/redis/redis.conf --appendonly yes
  • -v /mydocker/redis/conf/redis.conf:/etc/redis/redis.conf:挂载配置文件,提前将redis.conf放在里面

宿主机连接redis

[root@localhost ~]# redis-cli -h 192.168.99.102 -p 36079
# 由于没有输入密码,会提示认证失败
192.168.99.102:36079> get k1
(error) NOAUTH Authentication required.

# 认证密码
192.168.99.102:36079> auth redis_pass
OK

# 由于redis开启了aof持久化,之前容器删除后,由于指定了-v /mydocker/redis/data:/data和--appendonly yes,则直接读取里面的值
192.168.99.102:36079> get k1
"1"
192.168.99.102:36079> quit

# 也可以直接在命令上指定passwd
[root@localhost ~]# redis-cli -h 192.168.99.102 -p 36079 -a redis_pass
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.99.102:36079> get k1
"1"
192.168.99.102:36079> quit


[root@localhost ~]# tree /mydocker/redis/
/mydocker/redis/
├── conf
│   └── redis.conf
└── data
    └── appendonly.aof

本地镜像发布

阿里云创建仓库

  1. 访问 https://cr.console.aliyun.com/cn-chengdu/new 设置Registry登录密码;
  2. 创建镜像仓库,创建命名空间,设置仓库名称(可以和docker images中的REPOSITORY名称保持一致),摘要,点击下一步;
  3. 选择本地仓库(您可以通过命令行推送镜像到镜像仓库。),点击创建镜像仓库;
  4. 在镜像仓库中可以看到刚创建的仓库信息,点击管理,可以看到仓库详情。

操作流程

在仓库详情中,可以看到操作指南

推送镜像

登录阿里云docker

# 登录阿里云Docker Registry
[root@localhost ~]# docker login --username=阿里云登录用户名 registry.cn-chengdu.aliyuncs.com
Password: # 用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。以在访问凭证页面修改凭证密码。
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

标记本地镜像

标记本地镜像,将其归入某一仓库

# 镜像推送到Registry
[root@localhost ~]# docker images hello-world
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        14 months ago       1.84kB

[root@localhost ~]# docker tag fce289e99eb9 registry.cn-chengdu.aliyuncs.com/starmeow/hello-world:1.2

推送到镜像仓库

将本地的镜像上传到镜像仓库,要先登陆到镜像仓库

[root@localhost ~]# docker push registry.cn-chengdu.aliyuncs.com/starmeow/hello-world:1.2
The push refers to repository [registry.cn-chengdu.aliyuncs.com/starmeow/hello-world]
af0b15c8625b: Mounted from starmeow/docker 
1.2: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524
# 根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。

可以看到本地

[root@localhost ~]# docker images | grep -E "TAG|hello-world"
REPOSITORY                                              TAG                 IMAGE ID            CREATED             SIZE
hello-world                                             latest              fce289e99eb9        14 months ago       1.84kB
registry.cn-chengdu.aliyuncs.com/starmeow/hello-world   1.2                 fce289e99eb9        14 months ago       1.84kB

拉取镜像

# 先从本地删除
[root@localhost ~]# docker rmi registry.cn-chengdu.aliyuncs.com/starmeow/hello-world:1.2
Untagged: registry.cn-chengdu.aliyuncs.com/starmeow/hello-world:1.2
Untagged: registry.cn-chengdu.aliyuncs.com/starmeow/hello-world@sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a

[root@localhost ~]# docker images | grep -E "TAG|hello-world"
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        14 months ago       1.84kB

# 拉取阿里云的镜像
[root@localhost ~]# docker pull registry.cn-chengdu.aliyuncs.com/starmeow/hello-world:1.2
1.2: Pulling from starmeow/hello-world
Digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
Status: Downloaded newer image for registry.cn-chengdu.aliyuncs.com/starmeow/hello-world:1.2
registry.cn-chengdu.aliyuncs.com/starmeow/hello-world:1.2

# 查看拉取的镜像
[root@localhost ~]# docker images | grep -E "TAG|hello-world"
REPOSITORY                                              TAG                 IMAGE ID            CREATED             SIZE
hello-world                                             latest              fce289e99eb9        14 months ago       1.84kB
registry.cn-chengdu.aliyuncs.com/starmeow/hello-world   1.2                 fce289e99eb9        14 months ago       1.84kB

私有仓库搭建

registry的搭建

Docker 官方提供了一个搭建私有仓库的镜像 registry ,只需把镜像下载下来,运行容器并暴露5000端口,就可以使用了

拉取registry镜像

[root@localhost ~]# docker pull registry

[root@localhost ~]# docker images registry
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
registry            latest              708bc6af7e5e        6 weeks ago         25.8MB

启动registry

[root@localhost ~]# docker run -d -p 5000:5000 -v /mydocker/myregistry:/var/lib/registry --restart always --privileged=true --name myregistry registry
f58c15bd63f85c7f4d0dec8f36d8a41eea8d4bce21327f311a613955f3dbcbaa

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
f58c15bd63f8        registry            "/entrypoint.sh /etc…"   30 seconds ago      Up 30 seconds       0.0.0.0:5000->5000/tcp    myregistry
  • -v /mydocker/myregistry:/var/lib/registry:容器目录映射,如果容器被删除,镜像也不会删除
  • --privileged=true:centos7中的安全模块selinux把权限禁止了,加上这行是给容器增加执行权限
  • --restart always:自动重启

浏览器访问 http://192.168.99.102:5000/v2/ 可以得到{}

标记镜像

要通过docker tag 指定的镜像[:TAG] 私有仓库地址/仓库名[:新TAG]将该镜像标志为要推送到私有仓库

[root@localhost ~]# docker tag hello-world:latest 192.168.99.102:5000/hello-world:1.2

推送镜像

[root@localhost ~]# docker push 192.168.99.102:5000/hello-world:1.2
The push refers to repository [192.168.99.102:5000/hello-world]
Get https://192.168.99.102:5000/v2/: http: server gave HTTP response to HTTPS client

这是因为我们启动的registry服务不是安全可信赖的,需指定 主机的IP地址或者域名:5000。

配置insecure-registries

解决办法,在docker配置文件中添加"insecure-registries":["192.168.99.102:5000"]

[root@localhost ~]# vim /etc/docker/daemon.json 
[root@localhost ~]# cat /etc/docker/daemon.json 
{
     
  "registry-mirrors": [
    "https://dockerhub.azk8s.cn",
    "https://hub-mirror.c.163.com"
  ],
  "insecure-registries":["192.168.99.102:5000"]
}

[root@localhost ~]# systemctl restart docker

测试,如果重新加载也可以:systemctl reload docker

然后再次执行标签、推送

[root@localhost ~]# docker tag hello-world:latest 192.168.99.102:5000/hello-world:1.2
[root@localhost ~]# docker push 192.168.99.102:5000/hello-world:1.2
The push refers to repository [192.168.99.102:5000/hello-world]
af0b15c8625b: Layer already exists 
1.2: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524

访问 http://192.168.99.102:5000/v2/_catalog 可以看到{"repositories":["hello-world"]}

拉取镜像

[root@localhost ~]# docker pull 192.168.99.102:5000/hello-world:1.2

harbor的搭建

docker 官方提供的私有仓库 registry,用起来虽然简单 ,但在管理的功能上存在不足。 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,harbor使用的是官方的docker registry(v2命名是distribution)服务去完成。harbor在docker distribution的基础上增加了一些安全、访问控制、管理的功能以满足企业对于镜像仓库的需求。

官网: https://goharbor.io/

下载harbor

访问 https://github.com/goharbor/harbor/releases

下载harbor的离线版本

[root@localhost ~]# wget https://github.com/goharbor/harbor/releases/download/v1.10.1/harbor-offline-installer-v1.10.1.tgz

安装依赖

[root@localhost harbor]# yum install docker-compose -y
# docker也是必须的

docker-compose用法

在包含 docker-compose.yml 的目录下执行
基本命令:

  • -p 指定项目名称
  • build 构建项目中的服务容器 –force-rm 删除构建过程中的临时容器
  • --no-cache 构建过程中不使用 cache
  • --pull 始终通过 pull 来获取更新版本的镜像
  • docker-compose kill 强制停止服务容器
  • docker-compose logs 查看容器的输出 调试必备
  • docker-compose pause 暂停一个服务容器
  • docker-compose unpause 恢复暂停
  • docker-compose port 打印某个容器端口所映射的公共端口
  • docker-compose ps 列出项目中目前的所有容器 -q 只打印容器 id
  • docker-compose pull 拉取服务依赖的镜像
  • docker-compose restart -t 指定重启前停止容器的超时默认10秒
  • docker-compose rm 删除所有停止状态的容器先执行 stop
  • docker-compose run 指定服务上执行一个命令
  • docker-compose start 启动已经存在的服务容器
  • docker-compose stop 停止已经存在的服务容器
  • docker-compose up 自动构建、创建服务、启动服务,关联一系列,运行在前台,ctrl c 就都停止运行。如果容器已经存在,将会尝试停止容器,重新创建。如果不希望重新创建,可以 --no-recreate 就只启动处于停止状态的容器,如果只想重新部署某个服务,可以使用
  • docker-compose up --no-deps -d ,不影响其所依赖的服务
  • docker-compose up -d 后台启动运行,生产环境必备
  • docker-compose down 停止并删除容器

解压harbor

[root@localhost ~]# tar -zxvf harbor-offline-installer-v1.10.1.tgz
[root@localhost ~]# cd harbor
[root@localhost harbor]# ls
common  docker-compose.clair.yml  docker-compose.notary.yml  docker-compose.yml  ha  harbor.cfg  harbor.v1.10.1.tar.gz  install.sh  LICENSE  NOTICE  prepare

修改harbor.cfg

[root@localhost harbor]# vim harbor.cfg 

hostname = 192.168.99.102:12345  # 写你自己的网址或IP,公网访问要写公网IP,如果知名端口,默认运行在80或443
customize_crt = off  # 支持http访问

如果修改了监听的默认端口,那么docker-compose.yml也需要修改proxy---ports的端口- 12345:80

另外还有mysql、harbor等默认密码配置或其他相关参数设置。

安装

修改配置之后,进行安装
方式一:运行 ./install.sh安装,然后docker ps查看运行的服务
或集成clair漏洞扫描:./install.sh --with-clair(该功能用于页面上进行漏洞扫描,push镜像后点击扫描后,页面提示TypeError: Cannot set property 'scan_status' of undefined是正常的,他会后台扫描,过一会就有结果了),参考Harbor仓库镜像扫描原理
脚本会自动解压镜像文件并运行docker-compose

方式二:或者运行./prepare文件(修改配置文件之后需要重新生成一些内置配置),再手动运行docker-compose up -d

[root@localhost harbor]# ./install.sh 

[Step 0]: checking installation environment ...

Note: docker version: 19.03.7

Note: docker-compose version: 1.18.0


[Step 1]: preparing environment ...
Clearing the configuration file: ./common/config/adminserver/env
Clearing the configuration file: ./common/config/ui/env
Clearing the configuration file: ./common/config/ui/app.conf
Clearing the configuration file: ./common/config/ui/private_key.pem
Clearing the configuration file: ./common/config/db/env
Clearing the configuration file: ./common/config/jobservice/env
Clearing the configuration file: ./common/config/jobservice/config.yml
Clearing the configuration file: ./common/config/registry/config.yml
Clearing the configuration file: ./common/config/registry/root.crt
Clearing the configuration file: ./common/config/nginx/nginx.conf
Clearing the configuration file: ./common/config/log/logrotate.conf
loaded secret from file: /data/secretkey
Generated configuration file: ./common/config/nginx/nginx.conf
Generated configuration file: ./common/config/adminserver/env
Generated configuration file: ./common/config/ui/env
Generated configuration file: ./common/config/registry/config.yml
Generated configuration file: ./common/config/db/env
Generated configuration file: ./common/config/jobservice/env
Generated configuration file: ./common/config/jobservice/config.yml
Generated configuration file: ./common/config/log/logrotate.conf
Generated configuration file: ./common/config/jobservice/config.yml
Generated configuration file: ./common/config/ui/app.conf
Copied configuration file: ./common/config/uiprivate_key.pem
Copied configuration file: ./common/config/registryroot.crt
The configuration files are ready, please use docker-compose to start the service.


[Step 2]: checking existing instance of Harbor ...

Note: stopping existing Harbor instance ...
Stopping harbor-jobservice  ... done
Stopping nginx              ... done
Stopping harbor-ui          ... done
Stopping harbor-db          ... done
Stopping harbor-adminserver ... done
Stopping registry           ... done
Stopping redis              ... done
Stopping harbor-log         ... done
Removing harbor-jobservice  ... done
Removing nginx              ... done
Removing harbor-ui          ... done
Removing harbor-db          ... done
Removing harbor-adminserver ... done
Removing registry           ... done
Creating harbor-log ... done
Removing harbor-log         ... done
Removing network harbor_harbor

Creating harbor-db ... done
Creating harbor-ui ... done
Creating network "harbor_harbor" with the default driver
Creating nginx ... done
Creating registry ... 
Creating harbor-adminserver ... 
Creating redis ... 
Creating harbor-db ... 
Creating harbor-ui ... 
Creating harbor-jobservice ... 
Creating nginx ... 

✔ ----Harbor has been installed and started successfully.----

Now you should be able to visit the admin portal at http://192.168.99.102:12345. 
For more details, please visit https://github.com/vmware/harbor .

查看镜像和容器

[root@localhost harbor]# docker images | grep -E "TAG|vmware"
REPOSITORY                                              TAG                 IMAGE ID            CREATED             SIZE
vmware/redis-photon                                     v1.5.0              7c03076402d9        22 months ago       207MB
vmware/registry-photon                                  v2.6.2-v1.5.0       3059f44f4b9a        22 months ago       198MB
vmware/nginx-photon                                     v1.5.0              e100456182fc        22 months ago       135MB
vmware/harbor-log                                       v1.5.0              62bb6b8350d9        22 months ago       200MB
vmware/harbor-jobservice                                v1.5.0              aca9fd2e867f        22 months ago       194MB
vmware/harbor-ui                                        v1.5.0              1055166068d0        22 months ago       212MB
vmware/harbor-adminserver                               v1.5.0              019bc4544829        22 months ago       183MB
vmware/harbor-db                                        v1.5.0              82354dcf564f        22 months ago       526MB
  • redis-photon:redis存储
  • registry-photon:方的Docker registry,负责保存镜像
  • nginx-photon:负责流量转发和安全验证
  • harbor-log:harbor的日志收集、管理服务
  • harbor-jobservice:harbor的任务管理服务
  • harbor-ui:harbor的web页面服务
  • harbor-adminserver:harbor系统管理服务
  • harbor-db:由官方mysql镜像构成的数据库容器
[root@localhost harbor]# docker ps
CONTAINER ID        IMAGE                                  COMMAND                  CREATED             STATUS                        PORTS                                                                 NAMES
2dc70e644f66        vmware/nginx-photon:v1.5.0             "nginx -g 'daemon of…"   28 minutes ago      Up About a minute (healthy)   0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:12345->80/tcp   nginx
0ec9e6ed62c8        vmware/harbor-jobservice:v1.5.0        "/harbor/start.sh"       28 minutes ago      Up About a minute                                                                                   harbor-jobservice
6147e6c61c93        vmware/harbor-ui:v1.5.0                "/harbor/start.sh"       28 minutes ago      Up About a minute (healthy)                                                                         harbor-ui
e47ad932ddf9        vmware/redis-photon:v1.5.0             "docker-entrypoint.s…"   28 minutes ago      Up About a minute             6379/tcp                                                              redis
af5110e4f9f9        vmware/registry-photon:v2.6.2-v1.5.0   "/entrypoint.sh serv…"   28 minutes ago      Up About a minute (healthy)   5000/tcp                                                              registry
618a122905a6        vmware/harbor-adminserver:v1.5.0       "/harbor/start.sh"       28 minutes ago      Up About a minute (healthy)                                                                         harbor-adminserver
b8daf49a5cc7        vmware/harbor-db:v1.5.0                "/usr/local/bin/dock…"   28 minutes ago      Up About a minute (healthy)   3306/tcp                                                              harbor-db
86048aad6913        vmware/harbor-log:v1.5.0               "/bin/sh -c /usr/loc…"   28 minutes ago      Up About a minute (healthy)   127.0.0.1:1514->10514/tcp                                             harbor-log

查看Harbor状态

[root@localhost harbor]# docker-compose ps
       Name                     Command               State                                  Ports                               
---------------------------------------------------------------------------------------------------------------------------------
harbor-adminserver   /harbor/start.sh                 Up                                                                         
harbor-db            /usr/local/bin/docker-entr ...   Up      3306/tcp                                                           
harbor-jobservice    /harbor/start.sh                 Up                                                                         
harbor-log           /bin/sh -c /usr/local/bin/ ...   Up      127.0.0.1:1514->10514/tcp                                          
harbor-ui            /harbor/start.sh                 Up                                                                         
nginx                nginx -g daemon off;             Up      0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:12345->80/tcp
redis                docker-entrypoint.sh redis ...   Up      6379/tcp                                                           
registry             /entrypoint.sh serve /etc/ ...   Up      5000/tcp     

Web访问

防火墙允许端口,外部访问 http://192.168.99.102:12345/harbor/sign-in

[root@localhost harbor]# firewall-cmd --zone=public --add-port=12345/tcp
success

帐号密码默认是 admin/Harbor12345,这都可以在harbor.cfg配置的

push镜像

# 登录
[root@localhost harbor]# docker login -u admin 192.168.99.102:12345
Password: 
Error response from daemon: Get https://192.168.99.102:12345/v2/: http: server gave HTTP response to HTTPS client

登录http: server gave HTTP response to HTTPS client

多次docker login被refuse

这是因为 Docker 默认不允许非 HTTPS 方式推送镜像。我们可以通过 Docker 配置来取消这个限制,或者配置能够通过 HTTPS 访问的私有仓库。

[root@localhost harbor]# vim /etc/docker/daemon.json 
[root@localhost harbor]# cat /etc/docker/daemon.json 
{
     
  "registry-mirrors": [
    "https://dockerhub.azk8s.cn",
    "https://hub-mirror.c.163.com"
  ],
  "insecure-registries":["192.168.99.102:5000","192.168.99.102:12345"]
}
[root@localhost harbor]# systemctl reload docker
[root@localhost harbor]# docker info
# ...
 Insecure Registries:
  192.168.99.102:12345
  192.168.99.102:5000
  127.0.0.0/8
# 可以看到使用reload后,添加了
# ...

再次登录

[root@localhost harbor]# docker login -u admin 192.168.99.102:12345
Password: 
Error response from daemon: Get http://192.168.99.102:12345/v2/: unauthorized: authentication required

登录unauthorized: authentication required

首先检查login的用户名,密码是否一定正确。

检查common/templates/registry/config.yml配置文件中auth-token-realm的认证地址是否有更新

[root@localhost harbor]# cat ./common/config/registry/config.yml
# ...
auth:
  token:
    issuer: harbor-token-issuer
    realm: http://192.168.99.102:12345/service/token
    rootcertbundle: /etc/registry/root.crt
    service: harbor-registry

当修改过harbor.cfg配置文件时,需要使用./prepare脚本更新配置文件

[root@localhost harbor]# ./prepare

正常登录并push

[root@localhost harbor]# docker login -u admin 192.168.99.102:12345
Password: # Harbor12345
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

访问 http://192.168.99.102:12345/harbor/projects 创建项目,例如starmeow,查看详情,鼠标移动到“推送镜像”上可以看到推送链接

[root@localhost harbor]# docker images | grep -E "TAG|hello-world"
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
hello-world                 latest              fce289e99eb9        14 months ago       1.84kB

# 标记推送的镜像
[root@localhost harbor]# docker tag hello-world:latest 192.168.99.102:12345/starmeow/hello-world:1.2

# 查看被标记的镜像
[root@localhost harbor]# docker images | grep -E "TAG|hello-world"
REPOSITORY                                  TAG                 IMAGE ID            CREATED             SIZE
192.168.99.102:12345/starmeow/hello-world   1.2                 fce289e99eb9        14 months ago       1.84kB
hello-world                                 latest              fce289e99eb9        14 months ago       1.84kB

# 开始推送
[root@localhost harbor]# docker push 192.168.99.102:12345/starmeow/hello-world:1.2
The push refers to repository [192.168.99.102:12345/starmeow/hello-world]
af0b15c8625b: Pushed 
1.2: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524

Harbor日志

[root@localhost harbor]# tail -n 30 /var/log/harbor/
adminserver.log  clair-db.log     clair.log        jobservice.log   mysql.log        proxy.log        redis.log        registry.log     ui.log 

启停harbor

需要进入harbor解压文件内,用到Supported filenames: docker-compose.yml, docker-compose.yaml这种yml文件,否则就-f指定yml文件。

  • 停止服务: docker-compose stopdocker-compose -f docker-compose.yml stop
Stopping nginx              ... done
Stopping harbor-jobservice  ... done
Stopping harbor-ui          ... done
Stopping redis              ... done
Stopping registry           ... done
Stopping harbor-adminserver ... done
Stopping harbor-db          ... done
Stopping harbor-log         ... done
  • 开始服务: docker-compose startdocker-compose -f docker-compose.yml start
Starting log         ... done
Starting registry    ... done
Starting mysql       ... done
Starting adminserver ... done
Starting ui          ... done
Starting redis       ... done
Starting jobservice  ... done
Starting proxy       ... done

你可能感兴趣的:(Linux)