Docker基础_笔记

配置镜像加速器

阿里云镜像加速器:https://cr.console.aliyun.com

# 针对Docker客户端版本大于 1.10.0 的用户
# 您可以通过修改/新增daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://onau6ame.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

docker相关文件

# docker配置文件
# CentOS6
/etc/sysconfig/docker
# CentOS7
/usr/lib/systemd/system/docker.service
# 日志
$ cat /var/log/messages | grep docker

启/停docker服务

# 启动/停止/重启
systemctl start/stop/restart docker 
# 查看状态
systemctl status docker 
# 开机启动
systemctl enable docker

镜像

获取

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

docker pull ubuntu:16.04

​ 上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub 获取镜像。而镜像名称是 ubuntu:16.04 ,因此将会获取官方镜像 library/ubuntu 仓库中标签为 16.04 的镜像。

运行

[root@docker ~]# docker run -it --rm ubuntu:16.04 bash
root@3a31439393f0:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
root@3a31439393f0:/# exit
exit
[root@docker ~]# 

docker run:运行容器的命令。如果没有此镜像,会先pull再运行
-it:这是两个参数,一个是 -i :交互式操作,一个是 -t 终端。表示一个附有 tty 的交互会话
–rm:容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm
ubuntu:16.04:指用 ubuntu:16.04 镜像为基础来启动容器
bash:交互式的 Shell,用的是 bash
-d:后台运行镜像
-h:设定一个新的主机名
exit:退出这个容器

查看

# 列表包含了 仓库名 、 标签 、 镜像 ID 、 创建时间 以及 所占用的空间
[root@docker ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               5f2bf26e3524        11 days ago         123MB

标签

​ 镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个标签。如果拥有相同的 ID,说明对应的是同一个镜像。

# 修改标签
docker tag IMAGEID(镜像id) REPOSITORY:TAG(仓库:标签)
docker tag 5f2bf26e3524 ubuntu:new-tag

# 删除标签
docker rmi -f REPOSITORY:TAG(仓库:标签)

空间占用查看

# 查看镜像、容器、数据卷所占用的空间
[root@docker ~]# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              2                   1                   122.6MB             122.6MB (99%)
Containers          1                   0                   0B                  0B
Local Volumes       0                   0                   0B                  0B
Build Cache         0                   0                   0B                  0B
# docker system df -v 命令可以进一步查看空间占用细节,以确定是哪个镜像、容器或本地卷占用过高空间

虚悬镜像

​ 镜像列表中,有时还可以看到一个特殊的镜像,这个镜像既没有仓库名,也没有标签,均为

# 列出所有虚悬镜像
[root@docker ~]# docker image ls -f dangling=true
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              00285df0df87        12 days ago         340MB

一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,删除命令:docker image prune
该命令所清理的对象如下:
已停止的容器
未被任何容器使用的卷
未被任何容器所关联的网络
所有悬空的镜像

中间层镜像

​ docker images 列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数。

# docker images -a

​ 这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。

以特定格式显示

# 列出镜像ID
[root@docker ~]# docker image ls -q
5f2bf26e3524
5f2bf26e3524
fce289e99eb9
# 列出 镜像ID、仓库名 和 标签
[root@docker ~]# docker image ls --format "{{.ID}}: {{.Repository}}  {{.Tag}}"
5f2bf26e3524: ubuntu  16.04
5f2bf26e3524: ubuntu  new-tag
fce289e99eb9: hello-world  latest
# 以表格等距显示,有标题行,自己定义列
[root@docker ~]# docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID            REPOSITORY          TAG
5f2bf26e3524        ubuntu              16.04
5f2bf26e3524        ubuntu              new-tag
fce289e99eb9        hello-world         latest

删除本地镜像

​ docker image rm [ ID or NAME ] <镜像1> [<镜像2> …]

# 删除所有仓库名为 xx 的镜像
$ docker image rm $(docker image ls -q xx)
# 需要停止容器,解除容器对镜像的依赖,才可删除
# 停止所有容器
$ docker stop $(docker ps -a -q)
$ docker image rm fce289

容器

启/停

# 启动
$ docker start [container ID or NAMES]
# 停止所有容器
$ docker stop $(docker ps -aq)
# 启动所有状态为exited的容器
$ docker start $(docker ps -aq -f status=exited) 

进入容器

# 方式1
docker exec -it [container ID or NAMES] bash
# 方式2
yum install -y util-linux
docker inspect --format "{{.State.Pid}}" [container ID or NAMES]	# 获取pid
nsenter --target [PID] --mount --uts --ipc --net --pid	# 进入
# 启动一个名为mynginx的容器
[root@docker ~]# docker run -d --name mynginx nginx
# 编写脚本进入容器
[root@docker ~]# cat in.sh 
#!/bin/bash
CNAME=$1
CPID=$(docker inspect --format "{{.State.Pid}}" $CNAME)		# 获取容器进程IP
nsenter --target "$CPID" --mount --uts --ipc --net --pid	# 进入容器
[root@docker ~]# ./in.sh mynginx
mesg: ttyname failed: No such device
root@5dc5aff550e4:/#

查看容器详细信息

$ docker inspect [container ID or NAMES]
[
    {
        "Id": "23b077ae6d36d5f67f014c290495c15bd911f22043d0523eafb35ee0de087daf",
        "Created": "2023-03-08T06:02:31.267759389Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
...

#  可以用 grep 或 --format 参数(需要一个Go模板)来过滤
#  找出容器的 IP 地址
$ docker inspect [container ID or NAMES] | grep IPAddress
 "IPAddress": "172.17.0.4", 
 "SecondaryIPAddresses": null, 
$ docker inspect ––format {{.NetworkSettings.IPAddress}} [container ID or NAMES]
172.17.0.4

查看容器内的改动

​ Docker 容器使用联合文件系统(UFS),它允许多个文件系统以层级方式挂载,并表现为一个单一的文件系统。镜像的文件系统以只读方式挂载,任何对运行中容器的改变 则只会发生在它之上的可读写层。因此,Docker 只需查看最上面的可读写层,便可找出曾对运行系统所作的所有改变。

# 显示容器的文件系统的变化
$ docker diff [container ID or NAMES]
D /bin	# 删除
A /basket # 新增
A /basket/bash 
...

容器日志

$ docker logs [container ID or NAMES]
# -t:打印时间戳
# -f:持续打印日志变化

资源使用情况

$ docker stats [container ID or NAMES]
CONTAINER ID	NAME	CPU %	MEM USAGE / LIMIT    MEM %	NET I/O	BLOCK I/O	PIDS
6f95b1d24af5	nginx	0.00%	3.082MiB / 3.84GiB   0.08%	0B / 0B	21.2MB / 0B	5
# 获取所有运行中容器的统计数据
$ docker stats $(docker inspect -f {{.Name}} $(docker ps -q))

需要注意的是,除非对容器设置了内存限制,否则看到的内存限制是主机的内存总量,而不是容器的可用内存量。

删除容器

# 删除所有容器
$ docker rm $(docker ps -a -q)
# 删除已停止的容器
$ docker rm -v $(docker ps -aq -f status=exited)	# -v:删除关联的数据卷(/var/lib/docker/volumes/...)

$ docker container rm trusting_newton	# 删除一个处于终止状态的容器
# 如果要删除一个运行中的容器,可以添加 -f 参数。Docker 会发送 SIGKILL 信号给容器
$ docker container prune	# 清理掉所有处于终止状态的容器

对容器进行数据复制

# 容器文件复制到本地
$ docker cp [container ID or NAMES]:/root/A.txt . 
# 本地文件复制到容器
$ docker cp A.txt [container ID or NAMES]:/root/A.txt

端口映射

​ 假设一个容器中运行 Web 服务器。如何使外界能访问它呢?答案是通过 -p 或 -P 选项来“发布”端口。这个命令能够将主机的端口转发到容器上。

# -P(大写)随机分配端口映射;-p(小写)指定映射端口;
$ docker run -d -P --name mynginx1 nginx	# 让EXPOSE声明的端口都映射到主机的某一个随机端口上
$ docker run -d -p 81:80 --name mynginx2 nginx	# 81指:映射后的端口;80指:容器里的端口

# 例1
$ docker run -d -p 8000:80 nginx 
af9038e18360002ef3f3658f16094dadd4928c4b3e88e347c9a746b131db5444
$ curl localhost:8000
...
<title>Welcome to nginx!</title>
...
# 例2
$ docker run -d -P nginx
3423904dae5ba43a66c94872a8a51907bb613357654719a456aa5deea82ac025
$ docker port 3423904dae5ba 80	# 查看docker分配的端口
0.0.0.0:32770
$ curl localhost:32770
...
<title>Welcome to nginx!</title>
...

镜像/容器的导入导出

镜像

# 1.导出(save)/导入(load)
$ docker save -o xx.tar [REPOSITORY:TAG] or [container ID]
$ docker load -i xx.tar 

# 2.导出(save)/导入(load)
$ docker save > xx.tar [REPOSITORY:TAG] or [container ID]
$ docker load < xx.tar

# 其中-o和>表示输出到文件,xx.tar为目标文件
# 导入后的镜像的tag为空时,需要为镜像做tag
$ docker tag [container ID] [REPOSITORY:TAG]

容器

# 1.导出(export)/导入(import)
docker export [container ID or NAMES] > xx.tar	# 将导出容器快照到本地文件(.tar)
docker import xx.tar [REPOSITORY:TAG]
# 它只会导出文件系统;任何元数据,如映射端口、CMD 和 ENTRYPOINT 配置将会丢失。数据卷也不会包含在导出归档中

# 2.导出(export)/导入(import)
docker export -o xx.tar [container ID or NAMES]	# -o:表示输出到文件
cat xx.tar | docker import - [REPOSITORY:TAG]

构建镜像

手动

#  返回镜像id;-m :提交时的说明文字;
$ docker commit -m “xxxx” [container ID] xx/xx:v1
# 例
$ docker run -it --name cowsay --hostname cowsay debian bash
root@cowsay:/# apt-get update
... 
Reading package lists... Done 
root@cowsay:/# apt-get install -y cowsay fortune
...
root@cowsay:/# /usr/games/fortune | /usr/games/cowsay
 _______________________________________
/ You will be aided greatly by a person \
\ whom you thought to be unimportant.   /
 ---------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
root@cowsay:/# exit 
exit 
# 把它转成镜像,执行 docker commit 即可,无论容器是在运行中还是在停止状态都可以。执行 docker commit 时,你需要提供的参数包括容器的名称(“cowsay”)、新镜像的名称(“cowsayimage”),以及用来存放镜像的仓库名称(“test”):
$ docker commit cowsay test/cowsayimage
sha256:4df57a2ceb693148b0b0c0e9a66dba3ef90f80210138f19bd4407cc202205589
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test/cowsayimage    latest              4df57a2ceb69        19 seconds ago      191MB
...
# 相当于创建个在debian基础上安装了 cowsay 的镜像
$ docker run test/cowsayimage /usr/games/cowsay "Moo"
 _____
< Moo >
 -----
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Dockerfile

Dockerfile 中的每个指令执行后都会产生一个新的镜像层,而这个镜像层其实可以用来启动容器。一个新的镜像 层的建立,是用上一层的镜像启动容器,然后执行 Dockerfile 的指令后,把它保存为一个 新的镜像。

# 上述操作使用Dockerfile完成
$ mkdir cowsay
$ cd cowsay
$ touch Dockerfile
$ cat Dockerfile
FROM debian:wheezy
RUN apt-get update && apt-get install -y cowsay fortune
# 生成镜像
$ docker build -t test/cowsay-dockerfile .
...
$ docker run test/cowsay-dockerfile /usr/games/cowsay "Moo"
例:构建nginx的镜像
[root@docker nginx]# cat Dockerfile 
# Version 1.0
# Author: zhang san

# 基础镜像
FROM centos
# 维护者信息
MAINTAINER zhangsan
# 向镜像添加文件(文件与Dockerfile在同级目录)
ADD a.txt /usr/local/src
# 向镜像添加文件(如果是压缩包会自动解压)
ADD nginx-1.17.8.tar.gz /usr/local/src
ADD pcre-8.37.tar.gz /usr/local/src
# 执行命令
RUN yum install -y wget gcc gcc-c++ make openssl-devel
RUN useradd -s /sbin/nologin -M www
WORKDIR /usr/local/src/nginx-nginx-1.17.8
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --with-pcre=/usr/local/src/pcre-8.37 && make install
RUN echo "daemon off;" >> /usr/local/conf/nginx.conf
# 创建环境变量
ENV PATH /usr/local/nginx/sbin:$PATH
# 声明端口
EXPOSE 80
CMD ["nginx"]

# 开始构建,在Dockerfile文件所在目录执行
# 注意最后的"."为环境上下文,即Dockerfile所在目录 
[root@docker nginx]# docker build -t nginx-file:v1 .
FROM

​ **指定基础镜像。**FROM 必须为 Dockerfile 的第一条指令

基础镜像以“镜 像:标签”(IMAGE:TAG)的格式表示(例如 debian:wheezy)。如果省略标签,那么就被视为最新(latest),但建议一定要给标签设置为某个特定版本,以免出现任何意想不到的事情。

MAINTAINER

作者信息。

# 查看作者信息
$ docker inspect -f {{.Author}} IMAGE
RUN

在容器内执行指定的指令,并把结果保存下来。

RUN <命令行命令>		# <命令行命令> 等同于在终端操作的 shell 命令
COPY

​ 从上下文目录中复制文件/目录到镜像里指定路径。

# 两种格式
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

如果路径中有空格的话,那么必须使用 JSON 数组的格式。通配符可以用来指定多个文件或目录。
注意,不能指定上下文以外的 src 路径。

ADD

从构建环境的上下文或远程 URL 复制文件至镜像。由于 ADD 指令涵盖的功能相当广泛,一般最好还是使用相对简单的 COPY 指令来复制构建环境上下文的文件和目录,并用 RUN 指令配合 curl 或 wget 来下载远程资源(这样还可以在同一个指令中处理和删除下载文件)。
​ 如果 <源路径> 为一个 tar 压缩文件,压缩格式为 gzip , bzip2 以及 xz 的情况下, ADD 指令将会自动解压缩这个压缩文件到 <目标路径>去。(所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD )

优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

CMD

​ **当容器启动时执行指定的指令。**如果还定义了 ENTRYPOINT ,该指令将被解释为 ENTRYPOINT 的参数(在这种情况下,请确保使用的是 exec 格式)。CMD 指令也会被 docker run 命令中镜像名称后面的所有参数覆盖。假如定义了多个 CMD 指令,那么只有最后一个生效,前面出现过的 CMD 指令全部无效(包括出现在基础镜像中的那些)。

# 格式:
CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] # (推荐使用)
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数,如果docker run命令行结尾有参数指定,那CMD后面的参数不生效
  • 为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束;
  • CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖;
  • 如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
ENTRYPOINT

设置一个于容器启动时运行的可执行文件(以及默认参数)。任何 CMD 指令或 docker run 命令中镜像名称之后的参数,将作为参数传给这个可执行文件。ENTRYPOINT 指令通常用于提供“启动”脚本,目的是在解析参数之前,对变量和服务进行初始化。
​ 类似于 CMD ,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

# 把参数指定为容器的入口(entrypoint),覆盖任何 Dockerfile 中的 ENTRYPOINT 指令
$ docker run --entrypoint 

​ 但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。
​ 当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给ENTRYPOINT 指令,换句话说实际执行时,将变为: “”

ENV

设置镜像内的环境变量。(在镜像中这些变量仍然可用!)

# 格式
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
# 例
... 
ENV MY_VERSION 1.3 
RUN apt-get install -y mypackage=$MY_VERSION 
...
ARG

构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
​ 构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

# 格式
ARG <参数名>[=<默认值>]
VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
​ 避免重要的数据因容器重启而丢失;避免容器不断变大。

# 格式
VOLUME ["<路径1>", "<路径2>"...]
VOLUME /data	# 同步主机
EXPOSE

在Dockerfile中声明了哪些端口是将要开放。

​ 在构建容器时通过 -p/P做端口映射。(-P随机分配端口映射;-p指定映射端口;如果EXPOSE没有指定端口,那么使用 -P 参数无效)

# 格式
EXPOSE [port1] [port2] ...

# --expose 与 Dockerfile 的 EXPOSE 指令功能一样。指定容器将会使用的端口或端口范围,但并不会把端口打开。只有与 -P 参数同时使用,以及在连接容器时,才有真正意义
$ docker run --expose [port2]

EXPOSE 只是一个声明而已,真正使用是 docker run -p 主机端口:容器端口 或 -P 来指定的。

WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,以后各层的当前目录就被改为指定的目录,如该目录不存在,会新建。
​ 这个指令可多次使用。支持使用相对路径,按上次定义的 WORKDIR 解析。

# 格式
WORKDIR <工作目录路径>

# 将参数的路径设置为容器的工作目录。此选项会覆盖 Dockerfile 中的 WORKDIR 指令。
$ docker run -w <工作目录路径>
USER

指定后续命令(RUN、CMD 或 ENTRYPOINT)执行的用户;这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

# 新建用户组及用户
RUN groupadd -r [usergroup] && useradd -r -g [usergroup] [user]
USER [user]

# 设置命令运行时所使用的用户。此选项会覆盖 Dockerfile 中的 USER 指令
$ docker run -u <用户名>
ONBUILD

指定当镜像被用作另一个镜像的基础镜像时将会执行的指令。对于处理一些将要添加到子镜像的数据,这个指令将会非常有用(例如,把代码从一个已选定的目录中复制出来,并在执行构建脚本时使用它)

镜像层

​ Dockerfile 中的每个指令 执行后都会产生一个新的镜像层,而这个镜像层其实可以用来启动容器。一个新的镜像 层的建立,是用上一层的镜像启动容器,然后执行 Dockerfile 的指令后,把它保存为一个 新的镜像。
​ 当 Dockerfile 指令成功执行后,中间使用过的那个容器会被删掉,除非提供了 --rm=false 参数。由于每个指令的最终结果都只是个静态的镜像而已,本质上除了一个 文件系统和一些元数据以外就没有其他东西,因此即使指令中有任何正在运行的进程,最 后都会被停掉。这意味着,虽然你可以在 RUN 指令中执行一些持久的进程,譬如数据库或 SSH 服务,但到了处理下一个指令或启动容器的时候,它们就已经不再运行了。如果你需 要在启动容器的时候同时运行一个服务或进程,它必须从 ENTRYPOINT 或 CMD 指令中启动。

查看镜像所有层
$ docker history [REPOSITORY:TAG or IMAGE ID]
$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
ubuntu             1.0.0               acf9ad4cfadd        27 hours ago        197MB
$ docker history ubuntu:1.0.0
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
acf9ad4cfadd        27 hours ago        /bin/sh -c useradd -s /sbin/nologin -M www      329kB
b98e8df8a579        27 hours ago        /bin/sh -c #(nop) ADD file:1513396aa805d712d…   10B
13b66b487594        23 months ago       /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           23 months ago       /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B
<missing>           23 months ago       /bin/sh -c [ -z "$(apt-get indextargets)" ]     0B
<missing>           23 months ago       /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   195kB
<missing>           23 months ago       /bin/sh -c #(nop) ADD file:276b5d943a4d284f8…   196MB
# 可以运行历史镜像层
$ docker run -it  b98e8df8a579
root@81bbf026a7d6:/#
镜像层调试
$ cat Dockerfile
FROM busybox:latest 
RUN echo "This should work" 
RUN /bin/bash -c echo "This won't" 

# 尝试构建镜像
$ docker build -t echotest .
Sending build context to Docker daemon 2.048 kB 
Step 0 : FROM busybox:latest 
 ---> 4986bf8c1536 
Step 1 : RUN echo "This should work" 
 ---> Running in f63045cc086b # Docker为了执行指令而创建了一个临时容器,这是该容器的ID
This should work 
 ---> 85b49a851fcc # 这是由该容器所建立的镜像的ID
Removing intermediate container f63045cc086b # 临时容器在这里被删除
Step 2 : RUN /bin/bash -c echo "This won't" 
 ---> Running in e4b31d0550cd 
/bin/sh: /bin/bash: not found 
The command '/bin/sh -c /bin/bash -c echo"This won't"' returned a non-zero 
code: 127

# 运行出问题之前的镜像
$ docker run -it 85b49a851fcc
/# /bin/bash -c "echo hmm"
/bin/sh: /bin/bash: not found 
# 可以更清楚地看到问题的原因:busybox 镜像没有包含 bash shell

数据卷

​ 将容器内部的配置文件目录,挂载到宿主机指定目录下。

新建本地路径为容器数据卷

  • 默认挂载目录:/var/lib/docker/volumes/
  • 如果数据卷是容器内已有的目录,容器卷目录原有数据会被复制到本地卷目录中
  • 不能指定单个文件,只能指定目录
# 新建本地路径为容器数据卷
# 启动一个容器:名字叫volume-test1,主机名叫centos,创建并使用的数据卷/data
# -v /data:会在容器内创建/data文件夹
[root@docker ~]# docker run -it --name volume-test1 -h centos -v /data centos
[root@centos /]# cd /data/
[root@centos data]# touch aa.txt	# 在容器/data下新建aa.txt

# 查看对应容器/data挂载的本地卷路径
[root@docker ~]# docker inspect volume-test1 | grep Mounts -A 10
# 或者 docker inspect -f {{.Mounts}} volume-test1
        "Mounts": [
            {
                "Type": "volume",
                "Name": "cae4c832ed82a3664611672c61239f7fe80aaf4ca63bfa1cf6c5c14b0c9b600c",
                # Source目录对应这容器volume-test1里的/data目录
                "Source": "/var/lib/docker/volumes/cae4c832ed82a3664611672c61239f7fe80aaf4ca63bfa1cf6c5c14b0c9b600c/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
# 此时在本地_data和容器data的操作,都会互相同步。
[root@docker ~]# ls /var/lib/docker/volumes/cae4c832ed82a3664611672c61239f7fe80aaf4ca63bfa1cf6c5c14b0c9b600c/_data/
aa.txt	# 容器中新建的aa.txt文件; 

指定本地路径为容器数据卷

  • 如果数据卷是容器内已有的目录,容器卷目录原有数据会被隐藏;并且 docker rm -v 不会删除本地卷目录
  • 可以指定单个文件或目录
# -v 本地卷:容器卷; 
# -v /AA:/BB:ro	ro:挂载目录只读
[root@docker ~]# docker run -it --name volume-test1 -h centos -v 本地卷目录:容器卷目录[:ro] centos 

共享数据

数据卷共享
$ docker run -it --name 容器A --volumes-from 容器B 镜像
# 创建容器volume-test1,拥有数据卷/data
$ docker run -it --name volume-test1 -v /data centos
# 创建容器volume-test4,使用容器volume-test1的数据卷
$ docker run -it --name volume-test4 --volumes-from volume-test1 centos
# volume-test1和volume-test4都拥有数据卷/data,并且数据互通

需要注意的是,与卷关联的那个容器(在刚才的例子中,就是 volume-test1)无论正在运行与否,刚才的命令都能使用。只要至少存在着一个容器与卷关联,那么卷就不会被删除。

数据卷容器

​ 场景:专门起一个容器作为其他容器的数据卷使用。

​ 数据卷容器也是一个容器,但是它的目的是专门提供数据卷给其他容器挂载。复制卷始终具有相同的挂载点,数据卷的生命周期一直持续到没有容器使用它为止,类似于继承关系。

Dockerfile的VOLUME

​ 与执行 docker run 时提供 -v /data 参数的效果是相同的。

...
VOLUME /data	# 注意:Dockerfile 中 VOLUME 指令之后的所有指令不会对该数据卷有任何修改
...
# 【设置数据卷权限】
# 下面的 Dockerfile 不会有预期中的效果
FROM debian:wheezy 
RUN useradd foo 
VOLUME /data 
RUN touch /data/x	
RUN chown -R foo:foo /data	

# 正确的写法
FROM debian:wheezy 
RUN useradd foo 
RUN mkdir /data && touch /data/x 
RUN chown -R foo:foo /data 
VOLUME /data

容器互联

​ 场景:不通过ip互联,而是通过容器的名称或id来实现容器的互联。

​ Docker 的连接(link)是允许同一主机上的容器互相通信的最简单方法。当使用 Docker 默认的联网模型时,容器之间的通信将通过 Docker 的内部网络,这意味着主机网络无法看见这些通信。

# 建立一个与指定容器连接的内部网络接口
$ docker run --link [目标容器的名称]:[目标容器别名]

​ 使用 Docker 的连接也会把目标容器的别名和 ID 添加到主容器中的 /etc/hosts,允许主容器通过名称找到目标容器。

连接redis

$ docker pull redis
$ docker run --name myredis -d redis
5985b17fba106fb618e6584fdbc3f38295dd41ee797a9c0a335efd7601d69978

## 连接redis

# 方式1
# 主机上安装 redis-cli连接
$ docker inspect --format {{.NetworkSettings.IPAddress}}  myredis	# 获取容器IP
172.17.0.2
$ redis-cli -h 172.17.0.2 -p 6379
172.17.0.2:6379>

# 方式2
# 启动一个新的容器来运行 redis-cli,并把这两个容器连接上
$ docker run --rm -it --link myredis:redis redis /bin/bash
root@854ea635d68d:/data# redis-cli -h redis -p 6379
redis:6379> ping
PONG
redis:6379> set 'a' 123
OK
redis:6379> get a
"123"
redis:6379> exit
root@83400ca186aa:/data# exit
# --link myredis:redis 这个参数告诉 Docker 把新容器与现存的“myredis”容器连接起来;

# 并且在新容器中以“redis”作为“myredis”容器的主机名。为了实现这点,Docker 会在新容器中的 /etc/hosts 里添加一个新条目,把“redis”指向“myredis”的 IP 地址。这样就能够在执行redis-cli 的时候直接使用“redis”作为主机名,而不需想办法找出或传递 Redis 容器的 IP地址给 redis-cli
root@c6b90346ab20:/data# cat /etc/hosts
...
172.17.0.2      redis 5985b17fba10 myredis
172.17.0.3      c6b90346ab20

Docker 的连接功能目前还有一些不足之处。其中最大的不足也许就是连接只能是静态的。虽然连接在容器重启之后应该还能工作,但如果目标容器被替换了,连接是不会更新的。此外,目标容器必须在主容器之前启动,这意味着双向连接是不可能的。

访问仓库( Repository )

Docker Hub

$ docker login 		# 登录
$ docker logout 	# 退出

查找镜像

# 查找官方仓库中的镜像 
# --filter=stars=N  以指定仅显示收藏数量为 N 以上的镜像
$ docker search xx

# 查看自己仓库镜像
$ docker search [Docker Hub用户名]	

拉取镜像

$ docker pull xx	# 下载到本地

推送镜像

# 需要先打tag带上Docker Hub用户名
$ docker tag ubuntu:17.10 username/ubuntu:17.10	# username必须是自己Docker Hub用户名
$ docker push username/ubuntu:17.10		# 推送
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我会帮助你记录和学习Docker的知识点。下面是一份Docker学习笔记: 1. 什么是DockerDocker是一个开源的容器化平台,可以帮助开发者创建、打包、部署和运行应用程序,使应用程序可以在不同的环境中无缝运行。 2. Docker的优势有哪些? - 轻量化:Docker容器与虚拟机相比更加轻量级,启动和停止速度更快。 - 可移植性:Docker容器可以在任何支持Docker的平台上运行,无需担心环境不一致的问题。 - 隔离性:Docker使用容器技术进行隔离,每个容器之间相互独立,不会相互影响。 - 效率:Docker可以将应用程序及其依赖项打包为一个镜像,部署和扩展非常方便。 3. Docker常用的概念: - 镜像(Image):一个只读的模板,包含了运行应用程序所需的所有文件和依赖项。 - 容器(Container):基于镜像创建的可执行实例,可以运行、停止、删除等操作。 - 仓库(Registry):用于存储和分享镜像的地方,常用的有Docker Hub。 - Dockerfile:用于定义镜像构建过程的文本文件,包含了一系列的指令和配置。 4. Docker基本使用命令: - `docker pull <image-name>`:从仓库中拉取指定镜像。 - `docker run <image-name>`:创建并运行一个新的容器。 - `docker ps`:查看当前正在运行的容器。 - `docker stop <container-id>`:停止指定容器的运行。 - `docker rm <container-id>`:删除指定容器。 - `docker rmi <image-name>`:删除指定镜像。 5. Docker常见应用场景: - 镜像管理:可以通过Docker镜像进行应用程序开发、测试和部署。 - 微服务架构:通过容器化实现应用程序的模块化,方便管理和扩展。 - CI/CD:在持续集成和持续部署过程中使用Docker来构建、测试和发布应用程序。 这些是Docker学习过程中的一些基础知识点和常用命令。希望对你有帮助!如果你还有其他问题,可以随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值