1、历史

Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源。

Docker自2013年以来非常火热,无论是从 github 上的代码活跃度,还是Redhat在RHEL6.5中集成对Docker的支持, 就连 Google 的 Compute Engine 也支持 docker 在其之上运行。

2、概要说明

  • 容器之间互相隔离
  • 占用资源小

对比 VM
1_Docker基础 - 图3

3、常用指令

3.1、整体

docker 采用的是 C/S 架构,和常规 C/S 架构软件大致相同,主要由三部分构成:

  • Clients 客户端
  • Hosts 服务端

1_Docker基础 - 图4

镜像和容器常用命令转换关系

1_Docker基础 - 图5

指令 说明 **
attach 当前shell下 attach连接指定运行镜像
build 通过DockerFile 定制镜像
commit 提交当前容器为新的镜像
cp 从容器中拷贝指定文件或者目录到宿主机中
create 创建一个新的容器,同run,但不启动容器
diff 查看docker容器变化
events 从docker服务获取容器实时事件
exec 在已存在的容器上运行命令
export 导出容器的内容流作为一个tar归档文件[对应import]
history 展示一个镜像形成历史
images 列出系统当前镜像
import 从tar包中的内容创建一个新的文件系统映像[对应export]
info 显示系统相关信息
inspect 查看容器详细信息
kill kill指定docker容器
load 从一个tar包中加载一个镜像[对应save]
login 注册或者登录一个docker源服务器
logout 从当前docker registry退出
logs 输出当前容器日志信息
port 查看映射端口对应的容器内部源端口
pause 暂停容器
ps 列出容器列表
pull 从docker镜像源服务器拉取指定镜像或者库镜像
push 从docker镜像源服务器拉取指定镜像或者库镜像
restart 重启运行的容器
rm 移除一个或者多个容器
rmi 移除一个或多个镜像[无容器使用该镜像才可删除,否则需要删除相关容器才可继续或 -f 强制删除]
run 创建一个新的容器并运行一个命令
save 保存一个镜像为一个tar包[对应load]
search 在docker hub中搜索镜像
start 启动容器
stop 启动容器
tag 给源中镜像打标签
top 查看容器中的进程信息
unpause 取消暂停容器
version 查看docker版本号
wait 截取容器停止时的退出状态值

对于以上命令,如果不清楚其中命令 参数信息,可通过 docker command —help 查看详细说明

images 为例

  1. docker images --help

[root@VM-0-7-centos ~]# docker images —help

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

List images

Options:
-a, —all Show all images (default hides intermediate images)
—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
-q, —quiet Only show image IDs

1.环境搭建

1.1 安装 docker 服务端

  1. # 1. 卸载原本可能存在的旧版
  2. sudo yum remove docker \
  3. docker-client \
  4. docker-client-latest \
  5. docker-common \
  6. docker-latest \
  7. docker-latest-logrotate \
  8. docker-logrotate \
  9. docker-engine
  10. >>>>>
  11. Loaded plugins: fastestmirror, langpacks
  12. No Match for argument: docker
  13. No Match for argument: docker-client
  14. No Match for argument: docker-client-latest
  15. No Match for argument: docker-common
  16. No Match for argument: docker-latest
  17. No Match for argument: docker-latest-logrotate
  18. No Match for argument: docker-logrotate
  19. No Match for argument: docker-engine
  20. No Packages marked for removal
  21. # 2.安装 Docker Engine-Community
  22. # 使用 Docker 仓库进行安装
  23. # 在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库。之后,您可以从仓库安装和更新 Docker。
  24. # 2.1 设置仓库
  25. sudo yum install -y yum-utils \
  26. device-mapper-persistent-data \
  27. lvm2
  28. # 2.2 使用以下命令来设置稳定的仓库。
  29. sudo yum-config-manager \
  30. --add-repo \
  31. http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  32. # 2.3 真正开始安装Docker Engine-Community
  33. sudo yum install docker-ce docker-ce-cli containerd.io

因为 docker 服务器在国外,国内访问较慢,因此需要通过 镜像加速器 进行加速,国内主要的 docker 镜像加速器地址如下:

具体操作参考链接:菜鸟教程-Docker 镜像加速

以 阿里云 为例

  1. sudo mkdir -p /etc/docker
  2. sudo tee /etc/docker/daemon.json <<-'EOF'
  3. {
  4. "registry-mirrors": ["https://x4lyyl7d.mirror.aliyuncs.com"]
  5. }
  6. EOF
  7. sudo systemctl daemon-reload
  8. sudo systemctl restart docker

1.2 查看是否安装成功/查看版本

  1. docker -v
  2. # Docker version 20.10.11, build dea9396

1.3 卸载 docker

  1. # 卸载安装包
  2. yum remove docker-ce
  3. # 删除容器,镜像,配置文件
  4. rm -rf /var/lib/docker

2.启动 docker
  1. systemctl start docker
  2. >>>
  3. docker.service - Docker Application Container Engine
  4. Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
  5. Active: active (running) since Tue 2021-11-23 23:08:26 CST; 15s ago
  6. Docs: https://docs.docker.com
  7. Main PID: 30045 (dockerd)
  8. Tasks: 7
  9. Memory: 26.5M
  10. CGroup: /system.slice/docker.service
  11. └─30045 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

3.2、镜像

3.2.1、镜像搜索

先从本地,再从远端

  1. docker search xxxx

3.2.2、镜像远程拉取

  1. docker pull xxx

3.2.3、删除

  1. docker rmi xxx

删除时,需要先确认以该镜像运行的 容器 是否正在运行,否则会提示

Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be forced) - image is being used by stopped container 9faaf809b35c

  • 查看正在运行的容器信息

    1. # 查看容器运行历史
    2. docker ps -a

    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    eed53c659ffa hello-world “/hello” 30 minutes ago Exited (0) 30 minutes ago silly_maxwell
    9faaf809b35c hello-world “/hello” 7 days ago Exited (0) 7 days ago funny_ride

  • 根据 CONTAINER ID 删除指定 容器

    1. docker rm eed53c659ffa
  • 再次删除镜像
    上一步将 该镜像对应的容器都删除完毕后,再重新删除该镜像

    1. docker rmi xxx

批量(全部删除)

  1. docker rmi -f $(docker images -qa)

3.2.4、构建(Build)

主要用在 根据 Dockerfile 构建一个自定义镜像。具体 Dockerfile 的介绍 :xxxx

示例:

  1. cat Dockerfile
  2. FROM centos:6.7
  3. MAINTAINER Fisher "fisher@sudops.com"
  4. RUN /bin/echo 'root:123456' |chpasswd
  5. RUN useradd runoob
  6. RUN /bin/echo 'runoob:123456' |chpasswd
  7. RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
  8. EXPOSE 22
  9. EXPOSE 80
  10. CMD /usr/sbin/sshd -D

然后在当前文件夹下构建

  1. docker build -t 镜像名称 .

参数说明:

  • -t :指定要创建的目标镜像名
  • . :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径

3.2.5、提交

当想把进行一定自定义修改的 容器 反向生成一个全新的镜像时使用。

  1. docker commit -m="has update" -a="runoob" e218edb10161 runoob/ubuntu:v2

各个参数说明:

  • -m: 提交的描述信息
  • -a: 指定镜像作者
  • e218edb10161:容器 ID
  • runoob/ubuntu:v2: 指定要创建的目标镜像名

3.3、容器

3.3.1、启动容器

  1. docker run -it ubuntu /bin/bash

参数说明:

  • -i: 交互式操作。
  • -t: 终端。
  • -d:后台运行
  • ubuntu: ubuntu 镜像。
  • /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

如果要退出,直接输入 exit(也可以直接 ctrl + z) 强制中断退出,并结束容器

如果是以有交互的后台运行(-itd) 方式启动,则输入 exit 不会直接结束容器

3.3.2、启动已停止的容器

  • 查看容器运行历史

    1. docker ps -a
  • 重新启动容器

    1. docker start 容器ID

3.3.3、停止容器

  • 查看正在运行的容器

    1. docker ps
  • 停止(正在运行)的容器

    1. docker stop 容器

3.3.4、进入容器

此处进入的是以后台运行方式(有 -d) 运行的容器。容器启动后会进入后台,如果要进入容器,则有两种方式。

  • docker attach
  • docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。
  • attach
    用这种方式进入,如果输入 exit 退出,就会使容器停止

    1. docker attach 容器ID
  • exec

    1. docker exec -it 容器ID /bin/bash
    1. 如果从这个容器退出,容器不会停止

3.3.5、删除容器

删除的是已经停止了的容器,如果要删除正在运行容器,可以通过强制删除的方式

  1. docker rm -rf 容器ID

也可以先停止运行的容器,再删除

  • 查看已经停止了的容器

    1. docker ps -a
  • 删除容器(单个)

    1. docker rm 容器ID
  • 删除容器(所有)
    ```shell

    方法一:

    docker container prune

方法二:

docker rm $(docker ps -a -q)

  1. <a name="qeF3k"></a>
  2. ### 3.3.6、查看容器日志
  3. 查看容器应用的日志
  4. ```shell
  5. docker logs -f 容器ID

3.3.7、查看容器内进程信息

  1. docker top 容器ID

UID PID PPID C STIME TTY TIME CMD
root 10315 10296 0 11:43 pts/0 00:00:17 /usr/local/openjdk-11/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start

3.3.8、查看容器内信息

以 json 的形式显示容器内的配置信息,状态 等等

  1. docker inspect 容器ID

[
{
“Id”: “690274b4837e9720777cb89730b548bffdbf3acc6e8659605d944437820f7f76”,
“Created”: “2021-12-01T03:43:09.700425388Z”,
“Path”: “catalina.sh”,
“Args”: [
“run”
],
“State”: {
“Status”: “running”,
“Running”: true,
“Paused”: false,
“Restarting”: false,
“OOMKilled”: false,
“Dead”: false,
“Pid”: 10315,
“ExitCode”: 0,
“Error”: “”,
“StartedAt”: “2021-12-01T03:43:10.088403631Z”,
“FinishedAt”: “0001-01-01T00:00:00Z”
},
“Image”: “sha256:904a98253fbf7ce6ff0d5410387256c5fe4eedc5ff2fe130c821b6522558b5bf”,
“ResolvConfPath”: “/var/lib/docker/containers/690274b4837e9720777cb89730b548bffdbf3acc6e8659605d944437820f7f76/resolv.conf”,
“HostnamePath”: “/var/lib/docker/containers/690274b4837e9720777cb89730b548bffdbf3acc6e8659605d944437820f7f76/hostname”,
“HostsPath”: “/var/lib/docker/containers/690274b4837e9720777cb89730b548bffdbf3acc6e8659605d944437820f7f76/hosts”,
“LogPath”: “/var/lib/docker/containers/690274b4837e9720777cb89730b548bffdbf3acc6e8659605d944437820f7f76/690274b4837e9720777cb89730b548bffdbf3acc6e8659605d944437820f7f76-json.log”,
“Name”: “/cool_noyce”,
“RestartCount”: 0,
“Driver”: “overlay2”,
“Platform”: “linux”,
“MountLabel”: “”,
“ProcessLabel”: “”,
“AppArmorProfile”: “”,
“ExecIDs”: null,
“HostConfig”: {
“Binds”: null,
“ContainerIDFile”: “”,
“LogConfig”: {
“Type”: “json-file”,
“Config”: {}
},
“NetworkMode”: “default”,
“PortBindings”: {},
“RestartPolicy”: {
“Name”: “no”,
“MaximumRetryCount”: 0
},
“AutoRemove”: false,
“VolumeDriver”: “”,
“VolumesFrom”: null,
“CapAdd”: null,
“CapDrop”: null,
“CgroupnsMode”: “host”,
“Dns”: [],
“DnsOptions”: [],
“DnsSearch”: [],
“ExtraHosts”: null,
“GroupAdd”: null,
“IpcMode”: “private”,
“Cgroup”: “”,
“Links”: null,
“OomScoreAdj”: 0,
“PidMode”: “”,
“Privileged”: false,
“PublishAllPorts”: false,
“ReadonlyRootfs”: false,
“SecurityOpt”: null,
“UTSMode”: “”,
“UsernsMode”: “”,
“ShmSize”: 67108864,
“Runtime”: “runc”,
“ConsoleSize”: [
0,
0
],
“Isolation”: “”,
“CpuShares”: 0,
“Memory”: 0,
“NanoCpus”: 0,
“CgroupParent”: “”,
“BlkioWeight”: 0,
“BlkioWeightDevice”: [],
“BlkioDeviceReadBps”: null,
“BlkioDeviceWriteBps”: null,
“BlkioDeviceReadIOps”: null,
“BlkioDeviceWriteIOps”: null,
“CpuPeriod”: 0,
“CpuQuota”: 0,
“CpuRealtimePeriod”: 0,
“CpuRealtimeRuntime”: 0,
“CpusetCpus”: “”,
“CpusetMems”: “”,
“Devices”: [],
“DeviceCgroupRules”: null,
“DeviceRequests”: null,
“KernelMemory”: 0,
“KernelMemoryTCP”: 0,
“MemoryReservation”: 0,
“MemorySwap”: 0,
“MemorySwappiness”: null,
“OomKillDisable”: false,
“PidsLimit”: null,
“Ulimits”: null,
“CpuCount”: 0,
“CpuPercent”: 0,
“IOMaximumIOps”: 0,
“IOMaximumBandwidth”: 0,
“MaskedPaths”: [
“/proc/asound”,
“/proc/acpi”,
“/proc/kcore”,
“/proc/keys”,
“/proc/latency_stats”,
“/proc/timer_list”,
“/proc/timer_stats”,
“/proc/sched_debug”,
“/proc/scsi”,
“/sys/firmware”
],
“ReadonlyPaths”: [
“/proc/bus”,
“/proc/fs”,
“/proc/irq”,
“/proc/sys”,
“/proc/sysrq-trigger”
]
},
“GraphDriver”: {
“Data”: {
“LowerDir”: “/var/lib/docker/overlay2/b9892b76ec15efe2aa0ca4dfdf3ec82020e8d1ebacc48f936d5726743551fa88-init/diff:/var/lib/docker/overlay2/b26f5453c2bc0054925152abe19596875e8e2c22ff5f9a78e57a8936c392a5b3/diff:/var/lib/docker/overlay2/43e7f05c6d44e97d21d1b2917ff533246870cf4f77856a12f60791dde2e89ad0/diff:/var/lib/docker/overlay2/64de179aad06f1c2ec05ebe3c5b7d3749d2b85ea7a5ca63b3a0fc378281941d9/diff:/var/lib/docker/overlay2/f84b56821635e4f422a75b1f45937cd1197514c29f19180b02022f720e2945bc/diff:/var/lib/docker/overlay2/a80b72e2c662fcaa63bc2d4468e7d2d9e318e759efea4a2860f9634667578270/diff:/var/lib/docker/overlay2/b3d7ec37dfd68aab92881aa51d0039aa08995ca1611a6f8c35fc62da97bc6e5c/diff:/var/lib/docker/overlay2/7101466adb34e32f6ace57583593c10a8732a96d4cac961bc88f22534fb5604b/diff:/var/lib/docker/overlay2/9fb156af467499ef6b375bb993eebd4b04389806b7e0a2a3766de81de836a43f/diff:/var/lib/docker/overlay2/fcd1b6e4508c61e2a8ad72b408968f644d1208464789b749825e6841ab92998a/diff:/var/lib/docker/overlay2/d4a986360761cb5158c5376b2dade54dd2754592ea9e567fd52b482397be3266/diff”,
“MergedDir”: “/var/lib/docker/overlay2/b9892b76ec15efe2aa0ca4dfdf3ec82020e8d1ebacc48f936d5726743551fa88/merged”,
“UpperDir”: “/var/lib/docker/overlay2/b9892b76ec15efe2aa0ca4dfdf3ec82020e8d1ebacc48f936d5726743551fa88/diff”,
“WorkDir”: “/var/lib/docker/overlay2/b9892b76ec15efe2aa0ca4dfdf3ec82020e8d1ebacc48f936d5726743551fa88/work”
},
“Name”: “overlay2”
},
“Mounts”: [],
“Config”: {
“Hostname”: “690274b4837e”,
“Domainname”: “”,
“User”: “”,
“AttachStdin”: false,
“AttachStdout”: false,
“AttachStderr”: false,
“ExposedPorts”: {
“8080/tcp”: {}
},
“Tty”: true,
“OpenStdin”: true,
“StdinOnce”: false,
“Env”: [
“PATH=/usr/local/tomcat/bin:/usr/local/openjdk-11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”,
“JAVA_HOME=/usr/local/openjdk-11”,
“LANG=C.UTF-8”,
“JAVA_VERSION=11.0.13”,
“CATALINA_HOME=/usr/local/tomcat”,
“TOMCAT_NATIVE_LIBDIR=/usr/local/tomcat/native-jni-lib”,
“LD_LIBRARY_PATH=/usr/local/tomcat/native-jni-lib”,
“GPG_KEYS=A9C5DF4D22E99998D9875A5110C01C5A2F6059E7”,
“TOMCAT_MAJOR=10”,
“TOMCAT_VERSION=10.0.13”,
“TOMCAT_SHA512=fecfe06f38ff31e31fa43c15f2566f6fcd26bb874a9b7c0533087be81d1decd97f81eefeaca7ecb5ab2b79a3ea69ed0459adff5f9d55c05f5af45f69b0725608”
],
“Cmd”: [
“catalina.sh”,
“run”
],
“Image”: “tomcat”,
“Volumes”: null,
“WorkingDir”: “/usr/local/tomcat”,
“Entrypoint”: null,
“OnBuild”: null,
“Labels”: {}
},
“NetworkSettings”: {
“Bridge”: “”,
“SandboxID”: “a44fa548388253cf7828cd56c89059e14d9e4c8aec8141ab28768f1d2ece72de”,
“HairpinMode”: false,
“LinkLocalIPv6Address”: “”,
“LinkLocalIPv6PrefixLen”: 0,
“Ports”: {
“8080/tcp”: null
},
“SandboxKey”: “/var/run/docker/netns/a44fa5483882”,
“SecondaryIPAddresses”: null,
“SecondaryIPv6Addresses”: null,
“EndpointID”: “6cca0a21013096aa6af08a75decc9fb1503bcccbd4ab864184cf57cb3a885553”,
“Gateway”: “172.17.0.1”,
“GlobalIPv6Address”: “”,
“GlobalIPv6PrefixLen”: 0,
“IPAddress”: “172.17.0.2”,
“IPPrefixLen”: 16,
“IPv6Gateway”: “”,
“MacAddress”: “02:42:ac:11:00:02”,
“Networks”: {
“bridge”: {
“IPAMConfig”: null,
“Links”: null,
“Aliases”: null,
“NetworkID”: “694cac0be2cb57dfecdc3dda30cb41ae8906869998a9026376628e2f74b6ddff”,
“EndpointID”: “6cca0a21013096aa6af08a75decc9fb1503bcccbd4ab864184cf57cb3a885553”,
“Gateway”: “172.17.0.1”,
“IPAddress”: “172.17.0.2”,
“IPPrefixLen”: 16,
“IPv6Gateway”: “”,
“GlobalIPv6Address”: “”,
“GlobalIPv6PrefixLen”: 0,
“MacAddress”: “02:42:ac:11:00:02”,
“DriverOpts”: null
}
}
}
}
]

4、仓库管理(docker hub)

就像 github 一样,docker 也有集中管理镜像的地方,用户可以上传自定义镜像,也可以从上面拉去其他用户编写完成的 docker 镜像,其中也有部分 docker 官方维护的镜像。 docker pull xxx 其实也是从 docker hub 中拉取的。

官方链接:Docker Hub

操作参考: 菜鸟教程-Docker 仓库管理

可以在官方链接中注册一个账户(个人免费)

4.1、基本操作

4.1.1、登录

  1. docker login

4.1.2、提交本地镜像到远程仓库

  • 先给本地镜像打一个标签
    经过上述命令,本地会生成一个新的镜像

    1. docker tag 本地镜像名:本地镜像版本 远程仓库用户名/远程仓库镜像名:远程镜像版本号
  • 推送到远程
    镜像名命名规范: docker hub用户名/仓库名

    1. docker push 镜像名:镜像版本

    4.1.3、删除打包后的镜像

    如果想删除打包后的镜像,对于非latest版本的镜像,不能直接 docker rmi registry.cn-hangzhou.aliyuncs.com/hzx_dev/nginx ,需要说明详细要删除的版本docker rmi registry.cn-hangzhou.aliyuncs.com/hzx_dev/nginx:1.0.0
    image.png

4.1.4、登出

  1. docker logout
  2. >>>>>>>>>>
  3. Removing login credentials for https://index.docker.io/v1/

4.1.5、推送到远程镜像仓库

  • 登录阿里云Docker Registry
    用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
    您可以在访问凭证页面修改凭证密码。

    1. $ docker login --username=何昭翔 registry.cn-hangzhou.aliyuncs.com
  • 从Registry中拉取镜像

    1. $ docker pull registry.cn-hangzhou.aliyuncs.com/hezx_test/springboot:[镜像版本号]
  • 将镜像推送到Registry
    请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。

    1. $ docker login --username=何昭翔 registry.cn-hangzhou.aliyuncs.com
    2. $ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/hezx_test/springboot:[镜像版本号]
    3. $ docker push registry.cn-hangzhou.aliyuncs.com/hezx_test/springboot:[镜像版本号]

4.2、阿里云远程镜像仓库

登录地址:阿里云远程镜像仓库

4.2.1、登录

image.png

4.2.2、创建个人版实例

image.png
image.png
创建成功
image.png
image.png
image.png

4.2.3、远程链接登录

image.png
image.png

按照以上步骤就能成功登录连接远程阿里云镜像仓库了
image.png

4.2.4、创建远程仓库

此时如果想从本地拉取或者从本地推送镜像到远程镜像仓库,还需要进行仓库信息的配置。
仓库名组成:命名空间+仓库名
image.png
image.png
image.png
image.png
image.png
image.png
上传成功后截图
image.png

4.3、自建 Harbor

自建 Harbor 需要用到 docker-compose 相关技术,具体展开查看3_Docker进阶

5.Dockerfile

1.常用指令

RUN

  • 格式
    ```dockerfile RUN <命令行命令>

    <命令行命令> 等同于,在终端操作的 shell 命令。

RUN [“可执行文件”, “参数1”, “参数2”]

例如:

RUN [“./test.php”, “dev”, “offline”] 等价于 RUN ./test.php dev offline

  1. - 说明<br />用于执行后面跟着的命令行命令<br />**注意:**<br />Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如: 以上执行会创建 3 层镜像。可简化为以下格式: <br />如上,以 **&&** 符号连接命令,这样执行后,只会创建 1 层镜像
  2. ```dockerfile
  3. FROM centos
  4. RUN yum -y install wget
  5. RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
  6. RUN tar -xvf redis.tar.gz
  1. FROM centos
  2. RUN yum -y install wget \
  3. && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
  4. && tar -xvf redis.tar.gz

FROM

  • 格式

    1. FROM <image>
    2. # 或者 FROM <image>:<tag>
  • 说明
    FROM指令的功能是为后面的指令提供基础镜像,因此Dockerfile必须以FROM指令作为 第一条非注释指令 。从公共镜像库中拉取镜像很容易,基础镜像可以选择任何有效的镜像。
    在一个Dockerfile中FROM指令可以出现多次,这样会构建多个镜像。tag的默认值是latest,如果参数image或者tag指定的镜像不存在,则返回错误。

COPY

  • 格式

    1. COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
    2. COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
  • 说明
    复制命令,从上下文目录(物理机)复制文件或者目录到容器中指定路径
    例如:

    [—chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

    <源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。

    <目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

  1. COPY hom* /mydir/
  2. COPY hom?.txt /mydir/

ADD

  • 格式

    1. ADD [--chown=<user>:<group>] <源路径1>... <目标路径>
    2. ADD [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
  • 说明
    ADD 指令和 COPY 使用格式类似(同样需求下,官方推荐 COPY)功能也类似。最大的差异: ADD 在执行 <源文件> 为 tar 压缩文件的话, 会自动解压到容器内指定文件夹下

CMD

  • 格式

    1. CMD <shell 命令>
    2. CMD ["<可执行文件或命令>","<param1>","<param2>",...] # 推荐使用
    3. CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
  • 说明
    功能和 RUN 类似,但是两者执行的时间不一致

    • CMD 在 docker run 时运行
    • RUN 在 docker build 时运行

CMD 会被 docker run 时,被命令行中的参数所覆盖,当 Dockerfile 中存在多个 CMD 指令的时候,只有 最后一个会生效

ENTRYPOINT

  • 格式

    1. ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
  • 说明
    和CMD 功能类似,当 Dockerfile 中存在多个 ENTRYPOINT 指令时,只有最后一个会生效。但是不会被 docker run 命令行参数指定的指定所覆盖。
    如果 docker run 时使用了 —entrypoint 选项,将覆盖 CMD 指令指定的程序。一般是变参 使用 CMD ,这里的 CMD 等于是给 ENTRYPOINT 传参
    CMD 与 ENTRYPOINT 的使用示例:
    假设已通过 Dockerfile 构建了 nginx:test 镜像:
    ```dockerfile FROM nginx

ENTRYPOINT [“nginx”, “-c”] # 定参 CMD [“/etc/nginx/nginx.conf”] # 变参

  1. - 不传参数 <br />容器内会默认运行以下命令,启动主进程。
  2. ```dockerfile
  3. $ docker run nginx:test
  1. nginx -c /etc/nginx/nginx.conf
  1. - 传参运行 <br />容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
  1. $ docker run nginx:test -c /etc/nginx/new.conf
  1. nginx -c /etc/nginx/new.conf

ENV

  • 格式

    1. ENV <key> <value>
    2. ENV <key1>=<value1> <key2>=<value2>...
  • 说明
    设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
    示例:
    (假定宿主机已有 test.txt)

    1. FROM centos
    2. ENV MY_DIR /myDir/
    3. COPY test.txt $MY_DIR
    4. RUN cat $MY_DIR/test.txt

VOLUME

  • 格式

    1. VOLUME ["<路径1>", "<路径2>"...]
    2. VOLUME <路径>
  • 说明
    定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

    • 避免重要的数据,因容器重启而丢失,这是非常致命的。
    • 避免容器不断变大。
    • 在启动容器 docker run 的时候,我们可以 通过 -v 参数修改挂载点

docker run 会自动在宿主机中随机找一个文件路径进行映射关联
查看具体映射关系,可通过

  1. docker inspect 容器ID

在结果 json 中 搜索 Mounts ,示例如下:

  1. VOLUME [ "/data" ]
  2. //...
  3. "Mounts": [
  4. {
  5. "Type": "volume",
  6. "Name": "675bba435a6580f7c601a5c59c967616171fd3b3377dd0359f7d053ca0599ead",
  7. // Source 后面的地址就是宿主机的映射路径
  8. "Source": "/var/lib/docker/volumes/675bba435a6580f7c601a5c59c967616171fd3b3377dd0359f7d053ca0599ead/_data",
  9. // Destination:后面的地址就是容器内的映射地址
  10. "Destination": "/data",
  11. "Driver": "local",
  12. "Mode": "",
  13. "RW": true,
  14. "Propagation": ""
  15. }
  16. ],
  17. //...

至此,宿主机和容器内就有数据卷进行联通,如果在宿主机中该目录下操作文件,对应容器内也会实时更新。
如果容器停止,宿主机关联的路径并不会就此取消,还会继续存在,并保存之前关联的文件

EXPOSE

  • 格式

    1. EXPOSE <端口1> [<端口2>...]
  • 说明
    仅仅只是声明端口。

    • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
    • 会被 docker run 时被 参数 -p /-P 替换。在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
      ```dockerfile FROM centos EXPOSE 1234

> CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4698a9d2ad9c env_test “/bin/bash” 4 seconds ago Up 3 seconds 1234/tcp elastic_lamarr ```

WORKDIR

  • 格式

    1. WORKDIR <工作目录路径>
  • 说明
    指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
    近似 cd 切换当前路径
    示例: 则最后 pwd 输出的路径是 /a/b/c

    1. WORKDIR /a
    2. WORKDIR b
    3. WORKDIR c
    4. RUN pwd

USER

  • 格式

    1. USER <用户名>[:<用户组>]
  • 说明
    用于指定执行 后续命令 的用户和用户组,这边只是 切换 后续命令执行的用户( 用户和用户组必须提前已经存在 )。

LABEL

  • 格式

    1. LABEL <key>=<value> <key>=<value> <key>=<value> ...
  • 说明
    功能和旧版的 MAINTAINER 相同,都是给 容器信息中添加指定信息( docker inspect 容器ID
    示例:
    效果

    1. FROM centos
    2. LABEL MY_NAME="ZS"
    3. LABEL MY_AGE="18"
    1. //...
    2. "Config": {
    3. "Hostname": "e0d774560afc",
    4. "Domainname": "",
    5. "User": "",
    6. "AttachStdin": false,
    7. "AttachStdout": false,
    8. "AttachStderr": false,
    9. "Tty": true,
    10. "OpenStdin": true,
    11. "StdinOnce": false,
    12. "Env": [
    13. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    14. ],
    15. "Cmd": [
    16. "/bin/bash"
    17. ],
    18. "Image": "env_test",
    19. "Volumes": null,
    20. "WorkingDir": "",
    21. "Entrypoint": null,
    22. "OnBuild": null,
    23. "Labels": {
    24. //自定义 LABEL 信息
    25. "MY_AGE": "18",
    26. "MY_NAME": "ZS",
    27. "org.label-schema.build-date": "20210915",
    28. "org.label-schema.license": "GPLv2",
    29. "org.label-schema.name": "CentOS Base Image",
    30. "org.label-schema.schema-version": "1.0",
    31. "org.label-schema.vendor": "CentOS"
    32. }
    33. }
    34. //...

2.构建Dockerfile

主要用到的命令 :

  1. docker build [OPTIONS] PATH | URL | -

OPTIONS说明:

  • —build-arg=[] :设置镜像创建时的变量;
  • —cpu-shares :设置 cpu 使用权重;
  • —cpu-period :限制 CPU CFS周期;
  • —cpu-quota :限制 CPU CFS配额;
  • —cpuset-cpus :指定使用的CPU id;
  • —cpuset-mems :指定使用的内存 id;
  • —disable-content-trust :忽略校验,默认开启;
  • -f :指定要使用的Dockerfile路径;
  • —force-rm :设置镜像过程中删除中间容器;
  • —isolation :使用容器隔离技术;
  • —label=[] :设置镜像使用的元数据;
  • -m :设置内存最大值;
  • —memory-swap :设置Swap的最大值为内存+swap,”-1”表示不限swap;
  • —no-cache :创建镜像的过程不使用缓存;
  • —pull :尝试去更新镜像的新版本;
  • —quiet, -q :安静模式,成功后只输出镜像 ID;
  • —rm :设置镜像成功后删除中间容器;
  • —shm-size :设置/dev/shm的大小,默认值是64M;
  • —ulimit :Ulimit配置。
  • —squash :将 Dockerfile 中所有的操作压缩为一层。
  • —tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
  • —network: 默认 default。在构建期间设置RUN指令的网络模式

命令最后的 . 表示当前目录下 ,会自动识别当前目录下的 Dockerfile 文件,并构建成镜像。

简单示例:

  1. docker build -t my_centos .

6.网络-Dokcer0

参考链接:【csdn】Docker学习(五)docker网络(Docker0、evth-pair 技术、—link、docker network)

6.1、概述

docker 安装在 linux 后,就会创建一个 虚拟网卡

1_Docker基础 - 图23

等到容器启动后,docker 会给容器随机安排一个 ip ,并且不同容器之间默认是可以互相访问的。因为在 docker run 其实有一个参数 --network 这个是可以设置网络的。默认是直接用 docker0,所以可以理解 默认情况下, 容器是在同一个网络下,所以就互相可以访问。

1_Docker基础 - 图24

6.2、测试默认网络

先启动两个 centos 镜像

  1. # 第一个 centos 容器,名字为 centos01
  2. docker run -itd -P --name centos01 centos
  3. # 第二个 centos 容器,名字为 centos02
  4. docker run -itd -P --name centos02 centos

再分别查看两个容器的IP信息

  1. docker exec -it centos01 ip addr
  2. docker exec -it centos02 ip addr

image.png

6.2.1、先使用ip测试连通性

  1. docker exec -it centos01 ping 172.17.0.3

image.png

反之可行
image.png

6.2.2、再使用容器名(域名)进行测试

  1. docker exec -it centos02 ping 172.17.0.2

image.png
结果不通,说明默认情况下,网络只支持通过IP进行访问。
但这样就会造成新的问题:docker 每次重建后就会重新生成IP,IP也会随着进行变化。
针对以上问题,docker 两种解决方案,可以用来解决访问域名访问问题,并且也形成 网络隔离,防止不同作用的容器可能造成的网络冲突,影响。

  • 容器互联—link
  • Docker网络 network

    6.3、—link 容器互联

    设置容器互联需要在 容器启动时设置 --link 链接另一个已启动好的容器
    1. # --link
    2. docker run -itd --name centos03 --link centos01 centos
    3. # 测试,成功
    4. docker exec -it centos03 ping centos01
    5. # 反向测试,失败
    6. docker exec -it centos01 ping centos03
    image.png
    从上图可知,反向 ping 是不通的,说明 --link 是只有单向性,只有配置的映射单向互相访问,不支持双向

    6.4、network 自定义网络

    为了解决 --link 单向访问问题,并且为了形成 网络组(也即如果是在同一个组内,可以互相访问。如果不同组,则彼此访问不通),引入了新的指令:**network**通过这个指令,可以创建,加入自定义网络
  1. docker network COMMAND
  2. >>>
  3. Usage: docker network COMMAND
  4. Manage networks
  5. Commands:
  6. # 将一个容器加入到一个网络中
  7. connect Connect a container to a network
  8. # 创建一个网络
  9. create Create a network
  10. # 从一个网络中断开
  11. disconnect Disconnect a container from a network
  12. # 显示网络详情
  13. inspect Display detailed information on one or more networks
  14. # 查看网络列表
  15. ls List networks
  16. # 移除所有未被使用的网络
  17. prune Remove all unused networks
  18. # 移除一个或者多个网络
  19. rm Remove one or more networks
  20. Run 'docker network COMMAND --help' for more information on a command.

最终目标是 自定义多个网络,网络内容器之间可以通过域名访问,网络和网络之间形成网络隔离。并且通过设置,网络和指定容器之间也是可以访问

1_Docker基础 - 图30

6.3.1、inspect - 详情

查看网络中的详情

6.3.2、create - 创建

创建一个自定义网络

  1. docker network create --driver=bridge --subnet=192.168.0.0/16 br0

在运行容器时,通过 --network 网络名 指定该容器所在的网络

示例:

  1. docker run -itd --network my-net centos
  2. # 指定网络为 自定义的 my-net

查看对比 默认网络和自定义网络的差异:

  • 默认ip:172.17.0.3
  • 自定义 my-net : 192.168.0.2

1_Docker基础 - 图31

6.3.3、容器使用自定义网络

  1. # 创建时 通过 --network 声明连接的网络,默认 docker0
  2. docker run -itd --network br0 --name centos04 centos

6.3.4、connect - 连接

将一个容器加入到某一个网络中。

根据网络知识可知,在不同网段中的网络是不能访问的,以上述提到的 192.168.0.2172.17.0.3 为例

  1. docker exec -it 385f3fac3e47 ping 172.17.0.3
  2. # 385f3fac3e47 是使用自定义网络,ip 192.168.0.2
  3. # 测试结果是访问不通

但是可以将 172.17.0.3 所属的容器加入到网络中。

  1. docker network connect my-net d401cc22782d
  2. # docker network connect 自定义网络名 将要加入的容器ID
  3. # d401cc22782d 是 172.17.0.3所属的容器

通过 dokcer network inspect my-net 查看可得

1_Docker基础 - 图32

刚才 d401cc22782d 对应的容器已经加入 my-net 中,并且被赋予新的 ip,至此, d401cc22782d 该容器就变成 一个容器, 两个IP

最后再两个容器相互请求,进行对比,从下图可知,两个容器之间是可以访问的

1_Docker基础 - 图33

6.3.5、ls - 列表

  1. docker network ls

6.3.6、rm - 移除

  1. docker network rm 自定义网络名

在移除时,需要先停止,删除已经使用该自定义网络的容器