一般而言,Linux分为俩部分,*Linux内核*与*用户空间*,而真正的操作系统指的是Linux内核,
我们常用的Centos、Ubuntu等操作系统其实是不同厂商在Linux内核基础上添加自己的软件与工具集
(tools)形成的发布版本。
Docker中与镜像操作相关的命令都在docker image这条子命令下,通过docker image --help这条命令,可以看到docker image子命令的详细文档,如下:
Usage: docker image COMMAND
Manage images
Commands:
build Build an image from a Dockerfile(构建镜像的命令)
history Show the history of an image(显示镜像构建历史过程)
import Import the contents from a tarball to create a filesystem image(导入一个由容器导出的镜像)
inspect Display detailed information on one or more images(显示一个镜像的详细信息)
load Load an image from a tar archive or STDIN(从一个文件或标准输入流中导入镜像)
ls List images(查看镜像列表)
prune Remove unused images(删除虚悬镜像)
pull Pull an image or a repository from a registry(从仓库拉取镜像)
push Push an image or a repository to a registry(推送镜像到仓库)
rm Remove one or more images(删除镜像)
save Save one or more images to a tar archive (streamed to STDOUT by default)(保存镜像到文件)
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE(给镜像打标签)
在安装了Docker之后,我们本地并没有任何镜像,当然我们可以自己创建,不过更方便还是从Docker官方提供的仓库服务Docker Hub上拉取官方或第三方已经构建好的镜像。
拉取镜像可以使用docker image pull,其格式如下:
docker image pull [OPTIONS] NAME[:TAG|@DIGEST]
当然,docker image pull有更简洁的用法,如:
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
要拉取镜像,需要指定Docker Registry的URL和端口号,默认是Docker Hub,另外还需要指定仓库名和标签,仓库名和标签唯一确定一个镜像,而标签是可以省略的,如果省略,则默认使用laster作为标签名,而仓库名则由作者名和软件名组成。
所以,在省略参数后,比如我们想拉取centos镜像,可以使用下面简单的命令从Docker Hub上拉取:
docker pull centos
通过上面方法我们将镜像拉取到了本地,那要如何查看本地有哪有镜像呢?通过下面的命令我们可以查看本地的全部镜像:
docker image ls
当然Docker提供了更简洁的写法,如下:
docker images
要删除一个或多个本地镜像,可以使用下面命令:
docker image rm [option] IMAGE1,IMAGE2,...IMAGEn
也可以使用更简洁的方式,如下:
docker rmi [option] IMAGE1,IMAGE2,...IMAGEn
我们可以根据镜像长ID,短ID、镜像摘要以及镜像名称来删除镜像,如下:
docker rmi f7302e4ab3a8
docker rmi f7302
#查询镜像摘要
docker image ls --digests
#删除
docker rmi <摘要值>
docker rmi <仓库名>:<标签>
我们想要清除本地全部镜像时,可以使用下面的命令,不过一般不建议使用
docker rmi $(docker images -qa)
另外,一般如果镜像已经被用来创建了容器,使用上面的命令删除会报下面错误,告诉我们该镜像已经被使用,不允许被删除。
Error response from daemon: conflict: unable to remove repository reference "mysql:5.7" (must force) - container ccd406c07a78 is using its referenced image e1e1680ac726
对于已经被用于创建容器的镜像,删除方法有两种,一种是先把容器删除,再删除镜像,另一种则只需要再删除镜像的命令种跟一个-f参数便可,如:
$ docker rim -f f7302
如果想与别人共享某个镜像,除了从镜像服务仓库中pull镜像和把镜像push到仓库之外,其实我们还可以将本地构建好的镜像直接导出并保存为文件发送给别人,如下:
docker image save -o /test_image.tar.gz centos:latest
而当你拿到别人导出的镜像文件时,可以使用docker load命令把镜像加载到本地的Docker镜像列表中,如下:
docker load < /test_image.tar.gz
我们知道Docker镜像名由仓库名和标签组成,但有时候我们会看到仓库名和标签皆为
虚悬镜像一般是当我们使用docker pull拉取最新镜像时,生成了新的镜像,所以仓库名和标签都给了新的镜像,旧的镜像名和标签则被取消,成为虚悬镜像。
我们可以使用下面的命令打印所有的虚悬镜像:
docker image ls -f dangling=true
一般虚悬镜像已经没有什么作用了,所以可以清理掉,下面的命令可以清除所有的虚悬镜像:
docker image prune
不过,如果我们想要保留一些有用的虚悬镜像时,可以使用docker tag命令重新给镜像起个仓库名和标签:
docker tag 621d57f27e93 "test:1.0"
上面的例子都是直接使用官方提供的镜像,其实,除了从官方仓库或其他仓库拉取别人构建好的镜像外,我们也可以构建自己的镜像,一般由以下两种构建方式:
使用docker commit命令,我们可以将修改过的容器重新提交为一个镜像,如:
docker commit conntaner_id my-hello:1.0
使用这种方式构建的镜像,我们称为黑箱镜像,就是一个黑箱子一样,别人并不知道我们对容器做了哪些修改和操作,所以会对其安全性有所质疑。
所以不推荐使用这种方式构建镜像。
我们推荐编写Dockerfile来构建一种镜像,Docker Hub上的镜像都是采用这种方式构建的,采用这种方式的好处就是,我们不用把镜像分发给别人,而只是把Dockerfile和相应需要写入镜像的程序和数据发给别人,别人也能自己构建镜像,安全透明。
package main
import "fmt"
func main(){
fmt.Println("Hello Go")
}
将Go程序编译为可执行程序,如:
go build hello.go
# 从一个空白的镜像开始
FROM stratch
ADD hello /
# 执行
CMD /hello
$ docker build [OPTIONS] PATH | URL | -
# 注意最后的点(.)表示当前目录,即Dockerfile所在的目录
$ docker build -t "hello-go:1.0" .
上面只是简单演示了使用Dockerfile文件如何构建镜像,关于Dockerfile,还有许多更加深入地用法,我们之后有机再谈。
容器与镜像的关系,就如同JAVA中对象与类之间的关系。
容器是通过镜像来创建的,所以必须先有镜像才能创建镜像,而生成的容器是一个独立于宿主机的隔离进程,并且有属于容器自己的网络和命名空间。
我们前面介绍过,镜像是由多个中间层(Layer)组成,生成的镜像是只读的,但容器却是可读可写的,这是因为容器是再镜像上面添加一层读写层(writer/read layer)来实现的,如下图所示:
Usage: docker container COMMAND
Manage containers
Commands:
attach Attach local standard input, output, and error streams to a runnin g container
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 filesyste m
exec Run a command in a running container(在一个运行的容器中执行命令)
export Export a container's filesystem as a tar archive
inspect Display detailed information on one or more containers
kill Kill one or more running containers(杀死一个或多个正在运行的容器)
logs Fetch the logs of a container
ls List containers(显示本地容器列表)
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
prune Remove all stopped containers
rename Rename a container(重命名容器)
restart Restart one or more containers(重启一个或多个容器)
rm Remove one or more containers(删除一个或多个容器)
run Run a command in a new container(运行一个新的容器)
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(停止一个或多个容器)
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
wait Block until one or more containers stop, then print their exit codes
运行容器后,我们可以通过下面的命令查看本地所有容器:
docker container ls
# 更简洁写法
docker ps -a
上面命令执行的结果如下:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4f184f5ffb9 redis:latest "docker-entrypoint.s…" 6 seconds ago Up 4 seconds 0.0.0.0:6379->6379/tcp myredis
f7d970e7d4ce mysql:5.7 "docker-entrypoint.s…" 7 seconds ago Up 5 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp docker-mysql
有时候,我们只想查看容器的Id,可以使用下面的命令:
docker ps -aq
执行结果:
f4f184f5ffb9
f7d970e7d4ce
启动容器由几种不同的方式,最常见的方式是使用docker run命令可以通过镜像创建一个容器。
# /bin/bash表示运行容器后要执行的命令
$ docker run -it centos /bin/bash
docker run命令有一些比较常见的参数,比如容器是一种提供服务的守护进程,那么通常需要开放端口供外部访问,如:
docker run -p 80:80 nginx
也可以为容器指定一个名称,如:
$ docker run -p 80:80 --name webserver nginx
将容器设置为后台运行,如:
$ docker run -p 80:80 -d --name webserver nginx
另外一种则是使用docker start命令重新启动已经停止运行的容器,如:
# container_id表示容器的id
$ docker start container_id
而对于正在运行的容器,也可以通过docker restart命令重新启动,如:
# container_id表示容器的id
$ docker restart container_id
对于已经不需要的容器,可以使用docker stop命令停止其运行,如:
docker stop container_id1,container_id2...
批量停止容器,如:
docker stop $(docker ps -qa)
docker container rm container_id
# 更简洁的写法
docker rm container_id
也可以像上面批量停止容器一样,我们也可以批量删除容器,如:
$ docker rm $(docker ps -qa)
当容器正在运行时,我们想要强行删除,加上-f,如:
docker container rm -f container_id
# 更简洁的写法
docker rm -f container_id
对于正在运行的容器,我们也可以通过docker exec命令再次进入容器,如:
docker exec -it f4f184f5ffb9 /bin/bash
需要指定容器的Id或name,上面命令我们使用的时Id。
概括而言,Docker容器大体上有三种运行模式,如下:
docker run centos echo "hellowrold"
docker run -d -p 80:80 nginx
docker run -it centos /bin/bash
仓库(Repository)是集中存储镜像的地方,这里有个概念要区分一下,那就是仓库与仓库服务器(Registry)是两回事,像我们上面说的Docker Hub,就是Docker官方提供的一个仓库服务器,不过其实有时候我们不太需要太过区分这两个概念。
# 在命令行中输入
docker login
在输入账号密码登录到Docker Hub之后,便可以使用docker push命令把镜像推送到Docker Hub。
$ docker push 用户名/test:1.0
docker run -d -p 5000:5000 --restart=always --name registry registry
私有仓库访问地址:http://10.20.31.210:5000/v2/_catalog
# 从公共仓库拉取redis:6.2镜像
docker pull redis:6.2
# 重新打tag
docker tag redis:6.2 10.20.31.210:5000/redis:6.2
# 推送
docker push 10.20.31.210:5000/redis:6.2
当你第一次推送时,会报下面的错误:
解决办法:
将私有仓库信息添加到/etc/docker/daemon.json中。
1、配置私有仓库
# 打开文件
vim /etc/docker/daemon.json
# 文件添加下面信息
"insecure-registries": ["10.20.31.210:5000"]
sudo systemctl restart docker
sudo systemctl daemon-reload
3、再次进行推送:
# 推送
docker push 10.20.31.210:5000/redis:6.2
4、访问页面查看:http://10.20.31.210:5000/v2/_catalog
镜像是静态的概念,构建完成之后便不能在修改了,而容器则是一个动态的概念,使用Docker可以简单轻松地创建和删除容器,镜像与容器的关系,就如同JAVA中类与对象的关系,而仓库则是存储和分发镜像的地方。
特别感谢原创作者:原创作者链接