更多内容请点击 我的博客 查看,欢迎来访。
官方文档翻译
Docker 是基于Go语言实现的开源容器项目。利用操作系统本身已有的机制和特性,可以实现远超传统虚拟机的轻量级虚拟化。它是内核级的虚拟化。期望达到使项目运行环境“一次封装,到处运行的目的”。
Docker作为一个软件集装箱化平台,可以让开发者构建应用程序时,将它与其依赖环境一起打包到一个容器中,然后很容易地发布和应用到任意平台中。
利用docker创建的运行环境叫做docker容器,容器是通过docker镜像创建的,docker镜像文件可以放在私有仓库中也可以放在共有仓库中。最大的公有仓库是官方Docker Hub。
docker有3大核心:镜像、容器、仓库。
作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。
而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为 MB |
一般为 GB |
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。包含运行某个软件所需的所有内容,包含代码、运行时、库、环境变量和配置文件。
操作系统分为内核和用户空间。对于 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。
安装环境为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 拉取镜像有时会遇到困难,此时可以配置镜像加速器。国内很多云服务商都提供了国内加速器服务,例如:
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/
[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命令的参数。
[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.
列出本地主机的镜像
[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
[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]
[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
删除本地镜像,可以为镜像名,也可以镜像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
--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 外部端口:内部端口
映射端口
# 一个窗口启动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
-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
可以看到STATUS
为Up
,表示容器在后台运行着
查看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
查看该命令的所有选项。
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
对于运行中的容器,可以通过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
可以看到重启成功后STATUS
中Up
时间发生变化。
stop
类似于电脑正常关机
kill
类似于电脑拔电源
删除已停止的容器
[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 -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
查看指定容器运行的进程
[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
查看容器内部细节,以键值对的形式看到ID、创建时间、路径、参数、状态等详细信息。
[root@localhost ~]# docker inspect 90c18302fe0a
进入正在运行中的容器并以命令行交换:
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
# 直接在宿主机中显示容器中的执行结果
容器内的文件拷贝到宿主机上
[root@localhost ~]# docker cp 12396f0fe5e7:/var/log/dnf.log /root/
[root@localhost ~]# ls /root/ | grep log
dnf.log
提交容器副本使之成为一个新的镜像。
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 commit
生成新的镜像,使数据作为镜像的一部分保存下来,那么容器删除后,数据就没有了。
而容器数据卷就是为了能保存数据。类似于Redis中的rdb和aof文件。
卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但不属于联合文件系统,因此能够绕过Union Filre System提供一些用于持久存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生命周期,因此Docker不会在容器删除时删除其挂载的数据卷。
特点:
容器内添加数据卷
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中使用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
也实现了宿主机与容器内数据共享。
另外假如Docker挂载主机目录Docker内访问出现cannot open directory:Permission denied
,解决办法是,在挂载目录后多加一个--privileged=true
参数即可。即docker run -it username/centos --privileged=true
。
命名的容器挂载数据卷,其它同期通过挂载这个(父容器)实现数据共享,容器数据卷的容器,称之为数据卷容器。吧容器比喻为移动硬盘,移动硬盘上挂载移动硬盘,实现数据的传递依赖。
使用上面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
信息,Mounts
中Source
宿主机路径一样;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"]
#
表示注释;docker commit
的操作提交一个新的镜像层;从应用软件的角度看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个阶段:
Dockerfile面向开发,Docker镜像称为交付标准,Docker容器则涉及到部署与运维。
基础镜像,当前新镜像是基于哪个镜像的。
镜像维护者的姓名和邮箱地址
容器构建时需要运行的命令
当前容器对外暴露的端口号
指定在创建容器后,终端默认登录进来的工作目录
用来在构建镜像过程中设置环境变量
ENV MY_PATH /data
这个环境变量可以在后续的任何RUN
指令中使用,这就像在命令前面指定了环境变量前缀一样,也可以在其它指令中直接使用这些环境变量,比如WORKDIR $MY_PATH
,那么用户登录后就会切换到/data
目录。
将宿主机目录下的文件拷贝到镜像,且ADD
命令会自动处理URL和解压tar压缩包
类似ADD
,拷贝文件和目录到镜像中。
将从构建上下文目录中<源路径>的 文件/目录 复制到新的一层镜像内的<目标路径>位置。
容器数据卷,用于数据保存和持久化工作。
指定一个容器启动时要运行的命令。
Dockerfile中可以有多个CMD
指令,但只有最后一个生效,CMD
会被docker run
之后的参数替换。
指定一个容器启动时要运行的命令。
ENTRYPOINT
的目的和CMD
一样,都是在指定容器启动程序及参数。人为在docker run
添加参数会被追加,不会覆盖。
当构建一个被继承的Dockerfile时运行命令,父镜像在被子镜像继承后,父镜像的ONBUILD
被触发。
docker build -f /oath/Dockerfilexx -t [命名空间/]新镜像名[:TAG] .
如果Dockerfile文件的名字为Dockerfile
,可以不要-f
,即docker build -t [命名空间/]新镜像名[:TAG] .
构建时默认会使用缓存,如果不需要加上--no-cache
Base镜像(FROM scratch
),Dockerhub中绝大多数镜像都是通过在base镜像中安装和配置需要的软件构建出来的。
[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
[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
从下往上一层一层叠加的镜像。
对于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"]
# 创建一个新的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
指令
# 创建父镜像的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
# 创建一个文件夹,主要是放构建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文件
[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
的页面了
[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
# 搜索镜像
[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
:运行服务名字[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)
解决步骤
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
也可以使用宿主机的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
[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持久化[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
[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无任务可做而退出。其他主要的就是bind
、requirepass
、logfile
、port
等
在/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
docker images
中的REPOSITORY
名称保持一致),摘要,点击下一步;在仓库详情中,可以看到操作指南
# 登录阿里云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
Docker 官方提供了一个搭建私有仓库的镜像 registry ,只需把镜像下载下来,运行容器并暴露5000端口,就可以使用了
[root@localhost ~]# docker pull registry
[root@localhost ~]# docker images registry
REPOSITORY TAG IMAGE ID CREATED SIZE
registry latest 708bc6af7e5e 6 weeks ago 25.8MB
[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。
解决办法,在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
docker 官方提供的私有仓库 registry,用起来虽然简单 ,但在管理的功能上存在不足。 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,harbor使用的是官方的docker registry(v2命名是distribution)服务去完成。harbor在docker distribution的基础上增加了一些安全、访问控制、管理的功能以满足企业对于镜像仓库的需求。
官网: https://goharbor.io/
访问 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.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 只打印容器 iddocker-compose pull
拉取服务依赖的镜像docker-compose restart -t
指定重启前停止容器的超时默认10秒docker-compose rm
删除所有停止状态的容器先执行 stopdocker-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
停止并删除容器[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
[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
[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
防火墙允许端口,外部访问 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
配置的
# 登录
[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
多次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
首先检查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
[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
[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解压文件内,用到Supported filenames: docker-compose.yml, docker-compose.yaml
这种yml文件,否则就-f
指定yml文件。
docker-compose stop
或docker-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 start
或docker-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