$ sudo yum install yum-utils device-mapper-persistent-data lvm2
$
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce
$
$ sudo systemctl enable docker
$ sudo systemctl start docker
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
$
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce
$
$ sudo systemctl enable docker
$ sudo systemctl start docker
$ sudo dnf -y install dnf-plugins-core
$
$ sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
$ sudo dnf install docker-ce
$
$ sudo systemctl enable docker
$ sudo systemctl start docker
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
$
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce
$
$ sudo systemctl enable docker
$ sudo systemctl start docker
查看docker服务的日志
journalctl -u docker.service
journalctl -u docker.service|tail -n 200
可以查看docker服务启动的日志包括docker 服务不能起来的原因
例如因为不能创建网桥导致docker服务启动失败,十有八九是因为,防火墙开启导致docker的服务不能启动。可以通过命令 “systemctl stop firewalld” 关闭防火墙,重新启动 Docker 服务即可;systemctl status firewalld 查看防火墙开启状态。systemctl status docker 查看docker启动状态
Sep 06 23:23:11 DIGITAL-CAIJ dockerd[2109]: failed to start daemon: Error initializing network controller: error creating default "bridge" network: Failed to program NAT chain: COMMAND_FAILED: 'python-nftables' failed: internal:0:0-0: Error: Could not process rule: No such file or directory
这个命令能够显示 Docker C/S 结构中的服务端 ( docker daemon ) 和客户端 ( docker CLI ) 相关的版本信息。在默认情况下,docker CLI 连接的是本机运行的 docker daemon ,由于 docker daemon 和 docker CLI 通过 RESTful 接口进行了解耦,所以我们也能修改配置用于操作其他机器上运行的 docker daemon 。
查看docker客户端及服务端的版本信息
$ sudo docker version
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a
Built: Tue Aug 21 17:23:03 2018
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: 18.06.1-ce
API version: 1.38 (minimum version 1.12)
Go version: go1.10.3
Git commit: e68fc7a
Built: Tue Aug 21 17:25:29 2018
OS/Arch: linux/amd64
Experimental: false
如果想要了解 Docker Engine 更多相关的信息,我们还可以通过 docker info
这个命令。查看docker容器的详细信息,除了如上版本信息,还有镜像、容器数据卷、容器网络、Registry地址、物理配置等信息
$ sudo docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 18.06.0-ce
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
## ......
Live Restore Enabled: false
在 Linux 环境下,我们可以通过修改 /etc/docker/daemon.json
( 如果文件不存在,你可以直接创建它 ) 这个 Docker 服务的配置文件达到效果。
{
"registry-mirrors": [
"https://registry.docker-cn.com"
]
}
在修改之后,别忘了重新启动 docker daemon 来让配置生效哟:
$ sudo systemctl restart docker
要验证我们配置的镜像源是否生效,我们可以通过 docker info
来查阅当前注册的镜像源列表。
$ sudo docker info
## ......
Registry Mirrors:
https://registry.docker-cn.com/
## ......
如果要查看当前连接的 docker daemon 中存放和管理了哪些镜像,我们可以使用 docker images
这个命令 ( Linux、macOS 还是 Windows 上都是一致的 )。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
php 7-fpm f214b5c48a25 9 days ago 368MB
redis 3.2 2fef532eadb3 11 days ago 76MB
redis 4.0 e1a73233e3be 11 days ago 83.4MB
cogset/cron latest c01d5ac6fc8a 15 months ago 125MB
查看本地所有顶层镜像(top level)信息的命令,按照创建时间倒序展示 ;
docker images -a
,查看本地所有镜像信息的命令,包含中间层;docker images -q
,只显示镜像ID;docker images name:tag
,根据镜像name:tag来查看详细信息,不支持模糊搜索;docker history name:tag
,查看name:tag对应镜像的历史信息;要拉取镜像,我们可以使用 docker pull
命令,命令的参数就是我们之前所提到的镜像仓库名。
$ sudo docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
124c757242f8: Downloading [===============================================> ] 30.19MB/31.76MB
9d866f8bde2a: Download complete
fa3f2f277e67: Download complete
398d32b153e8: Download complete
afde35469481: Download complete
docker pull name:tag
,根据name和tag拉取镜像;docker search name
,根据镜像name进行搜索;除了直接通过 Docker Hub 网站搜索镜像这种方式外,我们还可以用 docker CLI 中的 docker search
这个命令搜索 Docker Hub 中的镜像。
docker search ubuntu
$ sudo docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 8397 [OK]
dorowu/ubuntu-desktop-lxde-vnc Ubuntu with openssh-server and NoVNC 220 [OK]
rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 171 [OK]
consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 129 [OK]
ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 95 [OK]
ubuntu-upstart Upstart is an event-based replacement for th… 89 [OK]
neurodebian NeuroDebian provides neuroscience research s… 54 [OK]
## ......
除了之前我们所提到的 docker images
可以列出本地 Docker 中的所有镜像外,如果我们要获得镜像更详细的信息,我们可以通过 docker inspect
这个命令。查看容器信息(包含配置、环境、网关、挂载、cmd等等信息)
$ sudo docker inspect redis:3.2
[
{
"Id": "sha256:2fef532eadb328740479f93b4a1b7595d412b9105ca8face42d3245485c39ddc",
"RepoTags": [
"redis:3.2"
],
"RepoDigests": [
"redis@sha256:745bdd82bad441a666ee4c23adb7a4c8fac4b564a1c7ac4454aa81e91057d977"
],
## ......
}
]
虽然 Docker 镜像占用的空间比较小,但日渐冗杂的镜像和凌乱的镜像版本会让管理越来越困难,所以有时候我们需要清理一些无用的镜像,将它们从本地的 Docker Engine 中移除。
删除镜像的命令是 docker rmi
,参数是镜像的名称或 ID。
$ sudo docker rmi ubuntu:latest
Untagged: ubuntu:latest
Untagged: ubuntu@sha256:de774a3145f7ca4f0bd144c7d4ffb2931e06634f11529653b23eba85aef8e378
Deleted: sha256:cd6d8154f1e16e38493c3c2798977c5e142be5e5d41403ca89883840c6d51762
Deleted: sha256:2416e906f135eea2d08b4a8a8ae539328482eacb6cf39100f7c8f99e98a78d84
Deleted: sha256:7f8291c73f3ecc4dc9317076ad01a567dd44510e789242368cd061c709e0e36d
Deleted: sha256:4b3d88bd6e729deea28b2390d1ddfdbfa3db603160a1129f06f85f26e7bcf4a2
Deleted: sha256:f51700a4e396a235cee37249ffc260cdbeb33268225eb8f7345970f5ae309312
Deleted: sha256:a30b835850bfd4c7e9495edf7085cedfad918219227c7157ff71e8afe2661f63
docker rmi
命令也支持同时删除多个镜像,只需要通过空格传递多个镜像 ID 或镜像名即可。
$ sudo docker rmi redis:3.2 redis:4.0
Untagged: redis:3.2
Untagged: redis@sha256:745bdd82bad441a666ee4c23adb7a4c8fac4b564a1c7ac4454aa81e91057d977
Deleted: sha256:2fef532eadb328740479f93b4a1b7595d412b9105ca8face42d3245485c39ddc
## ......
Untagged: redis:4.0
Untagged: redis@sha256:b77926b30ca2f126431e4c2055efcf2891ebd4b4c4a86a53cf85ec3d4c98a4c9
Deleted: sha256:e1a73233e3beffea70442fc2cfae2c2bab0f657c3eebb3bdec1e84b6cc778b75
## ......
docker rmi name:tag
,根据name和tag删除镜像,该镜像如果已经生成容器则不能删除;
docker rmi -f name:tag
,强制删除镜像,如论是否创建容器;
docker rmi -f ${docker images -q}
,强制删除本地所有镜像;
当我们选择好镜像以后,就可以通过 docker create
这个命令来创建容器了。
$ sudo docker create nginx:1.12
34f277e22be252b51d204acbb32ce21181df86520de0c337a835de6932ca06c3
要使用容器名操作容器,就先得给容器命名,在创建容器时,我们可以通过 --name
这个选项来配置容器名。
基于标签为 1.12 的 nginx 镜像
Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
$ sudo docker create --name nginx nginx:1.12
通过 docker create
创建的容器,是处于 Created 状态的,其内部的应用程序还没有启动,所以我们需要通过 docker start
命令来启动它。
$ sudo docker start nginx
在 Docker 里,还允许我们通过 docker run
这个命令将 docker create
和 docker start
这两步操作合成为一步,进一步提高工作效率。
$ sudo docker run --name nginx -d nginx:1.12
89f2b769498a50f5c35a314ab82300ce9945cbb69da9cda4b022646125db8ca7
通过 docker run
创建的容器,在创建完成之后会直接启动起来,不需要我们再使用 docker start
去启动了。
这里需要注意的一点是,通常来说我们启动容器会期望它运行在“后台”,而 docker run
在启动容器时,会采用“前台”运行这种方式,这时候我们的控制台就会衔接到容器上,不能再进行其他操作了。我们可以通过 -d
或 --detach
这个选项告诉 Docker 在启动后将程序与控制台分离,使其进入“后台”运行。
docker run -it name
,以交互方式新建启动容器,此处name为image的,非容器的,此时容器name随机;docker run --name newname name
,新启动的容器指定名称为newname;docker run -d name
,以守护方式启动容器;docker run -it -v local_path:container_path name
,-v是指挂载数据卷,使得主机和容器地址挂载;docker run --name name02 --volumes-from name01 name:tag
,启动name02容器,共享name01数据卷,name01称为数据卷容器;docker run -it --network=bridge name
,启动容器使用某个指定的网络;docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=admin --name mysql01 mysql:5.7
-d 后台运行 -p 端口映射 -v 卷挂载 -e 环境配置 安装启动mysql需要配置密码 --name 容器名字
语法:docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
OPTIONS说明:
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器ID;
-i: 以交互模式运行容器,通常与 -t 同时使用;
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
–name=“nginx-lb”: 为容器指定一个名称;
–dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
–dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
-h “mars”: 指定容器的hostname;
-e username=“ritchie”: 设置环境变量;
–env-file=[]: 从指定文件读入环境变量;
–cpuset=“0-2” or --cpuset=“0,1,2”: 绑定容器到指定CPU运行;
-m :设置容器使用内存最大值;
–net=“bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
–link=[]: 添加链接到另一个容器;
–expose=[]: 开放一个端口或一组端口;
docker restart containt_id
如果您没有容器的ID,可以通过以下命令获取正在运行的所有容器的ID:
docker ps -q
通过 docker ps
这个命令,我们可以罗列出 Docker 中的容器。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
89f2b769498a nginx:1.12 "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp nginx
默认情况下,docker ps
列出的容器是处于运行中的容器,如果要列出所有状态的容器,需要增加 -a
或 --all
选项。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
425a0d3cd18b redis:3.2 "docker-entrypoint.s…" 2 minutes ago Created redis
89f2b769498a nginx:1.12 "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp nginx
在 docker ps
的结果中,我们可以看到几项关于容器的信息。其中 CONTAINER ID、IMAGE、CREATED、NAMES 大家都比较容易理解,分别表示容器 ID,容器所基于的镜像,容器的创建时间和容器的名称。
结果中的 COMMAND 表示的是容器中主程序 ( 也就是与容器生命周期所绑定进程所关联的程序 ) 的启动命令,这条命令是在镜像内定义的,而容器的启动其实质就是启动这条命令。关于 COMMAND 的更多知识,我们在之后的 Docker 镜像制作中会更详细的解读。
结果中的 STATUS 表示容器所处的状态,其值和我们之前所谈到的状态有所区别,主要是因为这里还记录了其他的一些信息。在这里,常见的状态表示有三种:
有些读者有疑问,既然是列出容器,应该为命令取一些带有 ls
字眼的名字,为啥会用类似 Linux 中查看进程的 ps
呢?这其实有一部分历史原因,由于容器并非真的包裹住了进程,而只是隔离了进程,进程还是允许在宿主机操作系统之上的,所以列出镜像的过程到更新是查看正在运行的进程,故而有了这样的名字。
docker ps -q
,只显示容器ID;docker ps -a
,显示正在运行和历史运行过的容器信息;docker ps -l -n num
,显示最近创建的num个容器信息; -docker container ps
和docker container ls
的效果和docker ps
完全一样;要将正在运行的容器停止,我们可以使用 docker stop
命令。
$ sudo docker stop nginx
容器停止后,其维持的文件系统沙盒环境还是存在的,内部被修改的内容也都会保留,我们可以通过 docker start
命令将这个容器再次启动。
当我们需要完全删除容器时,可以通过 docker rm
命令将容器进行删除
$ sudo docker rm nginx
正在运行中的容器默认情况下是不能被删除的,我们可以通过增加 -f
或 --force
选项来让 docker rm
强制停止并删除容器,不过这种做法并不妥当。
docker top name
,查看name容器中的进程信息 ,docker container top name效果完全一样。
docker stats name
,查看某个容器的运行情况,docker container stats
,效果完全一样
docker logs [OPTIONS] CONTAINER
docker logs -f -t --tail=20 name
,查看name容器中的日志,-f表示跟踪日志输出,-t显示时间戳,–tail n,只显示最新的n条日志信息;docker inspect name
,查看某个容器的详细信息
很多时间,我们需要的操作并不仅仅是按镜像所给出的命令启动容器而已,我们还会希望进一步了解容器或操作容器,这时候最佳的方式就是让我们进入到容器了。
我们知道,容器是一个隔离运行环境的东西,它里面除了镜像所规定的主进程外,其他的进程也是能够运行的,Docker 为我们提供了一个命令 docker exec
来让容器运行我们所给出的命令。
这里我们试试用容器中的 more
命令查看容器的主机名定义。
$ sudo docker exec nginx more /etc/hostname
::::::::::::::
/etc/hostname
::::::::::::::
83821ea220ed
docker exec
命令能帮助我们在正在运行的容器中运行指定命令,这对于服务控制,运维监控等有着不错的应用场景。但是在开发过程中,我们更常使用它来作为我们进入容器的桥梁。
熟悉 Linux 的朋友们知道,我们操作 Linux 这个过程,并不是 Linux 内部的某些机能,而是通过控制台软件来完成的。控制台软件分析我们的命令,将其转化为对 Linux 的系统调用,实现了我们对 Linux 的操作。若不是这样,生涩的系统调用方法对普通开发者来说简直就是黑洞一般的存在,更别提用它们控制系统了。
在 Linux 中,大家熟悉的控制台软件应该是 Shell 和 Bash 了,它们分别由 sh 和 bash 这两个程序启动。
说到这里,有读者一定想到了,既然有这两个控制台程序,我们只要在容器里执行它们,然后通过它们去控制容器内的环境,岂不就可以“自由的飞翔”了吗。没错,这里说的进入容器,就是通过 docker exec
命令来启动 sh 或 bash,并通过它们实现对容器内的虚拟环境的控制。
由于 bash 的功能要比 sh 丰富,所以在能够使用 bash 的容器里,我们优先选择它作为控制台程序。
$ sudo docker exec -it nginx bash
root@83821ea220ed:/#
在借助 docker exec
进入容器的时候,我们需要特别注意命令中的两个选项不可或缺,即 -i
和 -t
( 它们俩可以利用简写机制合并成 -it
)。
其中 -i
( --interactive
) 表示保持我们的输入流,只有使用它才能保证控制台程序能够正确识别我们的命令。而 -t
( --tty
) 表示启用一个伪终端,形成我们与 bash 的交互,如果没有它,我们无法看到 bash 内部的执行结果。
熟悉通过在容器中执行控制台程序进而进入容器这种方法,在开发过程中你能更轻松的观察容器中发生了什么,也更容易排查程序或者环境引起的问题
Docker exec命令的基本语法如下:
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
命令详解
OPTIONS
:可选参数,用于设置执行选项。CONTAINER
:容器名称或ID,指定要执行命令的容器COMMAND
:要在容器内执行的命令ARG
:命令的参数,可以有多个options常用参数
docker exec -it 13f607add223 bash
docker exec -it test /bin/bash
docker exec
命令进入容器后,再使用exit
命令退出容器,容器仍将保持运行docker exec
命令都会分配一个不同的 tty 给用户docker exec
命令进入容器而不是docker attach
进入正在运行的 test 容器 CLI模式:
drwxrwxrwt 2 root root 4096 Jul 6 13:45 work
root@DIGITAL-CAIJ:/# docker exec -it tomcat bash
root@399ef59dde14:/usr/local/tomcat# ls
bin conf lib logs NOTICE RELEASE-NOTES temp webapps.dist
BUILDING.txt CONTRIBUTING.md LICENSE native-jni-lib README.md RUNNING.txt webapps work
root@399ef59dde14:/usr/local/tomcat#
root@hikvision-CAIJ:/# docker exec -it tomcat ls -l
total 156
drwxr-xr-x 2 root root 4096 Jul 25 23:16 bin
-rw-r--r-- 1 root root 20123 Jul 6 13:45 BUILDING.txt
drwxr-xr-x 1 root root 4096 Aug 15 12:42 conf
-rw-r--r-- 1 root root 6210 Jul 6 13:45 CONTRIBUTING.md
drwxr-xr-x 2 root root 4096 Jul 25 23:15 lib
-rw-r--r-- 1 root root 60393 Jul 6 13:45 LICENSE
drwxrwxrwt 1 root root 4096 Aug 15 12:42 logs
drwxr-xr-x 2 root root 4096 Jul 25 23:16 native-jni-lib
-rw-r--r-- 1 root root 2333 Jul 6 13:45 NOTICE
-rw-r--r-- 1 root root 3398 Jul 6 13:45 README.md
-rw-r--r-- 1 root root 6776 Jul 6 13:45 RELEASE-NOTES
-rw-r--r-- 1 root root 16076 Jul 6 13:45 RUNNING.txt
drwxrwxrwt 2 root root 4096 Jul 25 23:15 temp
drwxr-xr-x 2 root root 4096 Jul 25 23:15 webapps
drwxr-xr-x 7 root root 4096 Jul 6 13:45 webapps.dist
drwxrwxrwt 2 root root 4096 Jul 6 13:45 work
docker exec -it tomcat_muller start.sh
这个命令将运行tomcat_muller
容器中的start.sh
脚本。
root@DIGITAL-CAIJ:/# docker exec -itw /usr/local/ tomcat pwd
/usr/local
root@DIGITAL-CAIJ:/# docker exec -itw /usr/local/ tomcat ls
bin etc games include lib man sbin share src tomcat
root@DIGITAL-CAIJ:/#
root@DIGITAL-CAIJ:/# docker exec -it -u root tomcat bash
root@399ef59dde14:/usr/local/tomcat#
注意
docker exec
命令进入容器后,再使用exit
命令退出容器,容器仍将保持运行docker exec
命令都会分配一个不同的 tty 给用户docker exec
命令进入容器而不是docker attach
作用:进入容器正在执行的终端,进入当前容器后开启一个新的终端,可以在里面操作。进入正在运行的容器name的命令行,显示该容器的运行信息;
语法格式
docker attach [OPTIONS] CONTAINER
ptions 说明
option | 说明 |
---|---|
–detach-keys | 指定退出attach模式的快捷键序列,默认是 CTRL-p |
–no-stdin | 是否挂你标准输入,默认是打开 |
–sig-proxy | 是否代理收到的系统信号给应用进程,默认为true |
和docker exec 的区别
docker exec
进入容器正在执行某个命令的终端,不能在里面操作;多个窗口同时attach到同一个容器时,所有窗口同步显示;当某个窗口因命令阻塞,其他窗口也无法操作
docker attach
进入容器正在执行某个命令的终端,不能在里面操作;多个窗口同时attach到同一个容器时,所有窗口同步显示;当某个窗口因命令阻塞,其他窗口也无法操作
Docker 为我们提供了一个 docker attach
命令,用于将当前的输入输出流连接到指定的容器上。
$ sudo docker attach nginx
这个命令最直观的效果可以理解为我们将容器中的主程序转为了“前台”运行 ( 与 docker run
中的 -d
选项有相反的意思 )。
由于我们的输入输出流衔接到了容器的主程序上,我们的输入输出操作也就直接针对了这个程序,而我们发送的 Linux 信号也会转移到这个程序上。例如我们可以通过 Ctrl + C 来向程序发送停止信号,让程序停止 ( 从而容器也会随之停止 )。
在实际开发中,由于 docker attach
限制较多,功能也不够强大,所以并没有太多用武之地,这里我们就一笔带过,不做详细的解读了。
docker commit -a="author" -m="commit info" name newname:tag
,写上作者、提交信息,并将当前容器打包为newname:tag的容器;docker cp name:/container_path local_path
,将name容器中container_path路径下内容cp到宿主机的local_path路径下;docker cp local_path name:/container_path
,将宿主机的local_path路径下内容cp到name容器中container_path路径下docker cp 容器与宿主机之间的数据拷贝
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH 容器往宿主机复制
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH 宿主机往容器复制
CONTAINER
,可以是正在运行或已停止的容器,名称或ID均可SRC_PATH
,源文件或目录在容器内的路径DEST_PATH
,目标路径在主机上的位置注:需要注意的是,如果
以/
结尾,表示目标路径是一个目录,此时需要保证目标路径存在。如果
不以/
结尾,表示目标路径是一个文件,此时需要保证目标路径的上层目录存在。
当DEST_PATH
存在并且是一个文件 ,目标被源文件的内容覆盖
当DEST_PATH
存在并且是目录,使用 SRC_PATH
中的基本名称将文件复制到此目录中
SRC_PATH指定目录
当DEST_PATH存在并且是目录时,复制将正常复制
SRC_PATH 不以 /. 结尾,源目录复制到此目录
SRC_PATH 以 /. 结尾,源目录的内容被复制到该目录中
当DEST_PATH存在并且是一个文件时,复制将报错,因为无法将目录复制到文件中当DEST_PATH 不存在时,将新创建 DEST_PATH 为路径的目录,并将源目录的内容复制到该目录中
options可用参数
-a:将复制的文件或目录保留其原始属性,包括所有者、权限等。
-L:如果SRC_PATH是一个符号链接,则复制链接指向的文件或目录。
-p:保留源文件或目录的时间戳。
-R或-r:递归复制整个目录。
ocker update [OPTIONS] CONTAINER [CONTAINER...]
Docker Update是一种非常有用的Docker命令,它可以帮助用户更新镜像和容器。当容器或镜像中存在漏洞时,更新命令可以立即修复并保护系统安全
说明:
使用docker run命令创建容器时没有添加参数 --restart=always ,导致的后果是:当 Docker 重启时,容器未能自动启动。
# docker run -ti -p 9501:9501 --restart=always -v /data/nginx:/nginx:latest
–restart=always : 开机启动,失败也会一直重启;
–restart=on-failure:10 : 表示最多重启10次
docker run --restart具体参数值详细信息
no - 容器退出时,不重启容器;
on-failure - 只有在非0状态退出时才从新启动容器;
always - 无论退出状态是如何,都重启容器;
# docker update --restart=always 容器名字或者容器ID
立即生效需要重启docker
# systemctl restart docker
不然就等到它下次重启自动生效。
要让一个容器连接到另外一个容器,我们可以在容器通过 docker create
或 docker run
创建时通过 --link
选项进行配置。
$ sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql`
$ sudo docker run -d --name webapp --link mysql webapp:latest`
假设我们在 Web 应用中使用的是 JDBC 进行数据库连接的,我们可以这么填写连接。
String url = "jdbc:mysql://mysql:3306/webapp";
我们在 docker ps 的结果中可以看到容器暴露给其他容器访问的端口。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95507bc88082 mysql:5.7 "docker-entrypoint.s…" 17 seconds ago Up 16 seconds 3306/tcp, 33060/tcp mysql
端口的暴露可以通过 Docker 镜像进行定义,也可以在容器创建时进行定义。在容器创建时进行定义的方法是借助 --expose
这个选项。
$ sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --expose 13306 --expose 23306 mysql:5.7
暴露后我们可以在 docker ps
中看到这两个端口已经成功的打开。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c4e645f21d7 mysql:5.7 "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 3306/tcp, 13306/tcp, 23306/tcp, 33060/tcp mysql
纯粹的通过容器名来打开容器间的网络通道缺乏一定的灵活性,在 Docker 里还支持连接时使用别名来使我们摆脱容器名的限制。
$ sudo docker run -d --name webapp --link mysql:database webapp:latest
在这里,我们使用 --link
的形式,连接到 MySQL 容器,并设置它的别名为 database。当我们要在 Web 应用中使用 MySQL 连接时,我们就可以使用 database 来代替连接地址了。
String url = "jdbc:mysql://database:3306/webapp";
我们通过 docker inspect
命令查看容器,可以在 Network 部分看到容器网络相关的信息。这里我们能够看到 mysql 容器在 bridge 网络中所分配的 IP 地址,其自身的端点、Mac 地址,bridge 网络的网关地址等信息。
Docker 默认创建的这个 bridge 网络是非常重要的,理由自然是在没有明确指定容器网络时,容器都会连接到这个网络中。在之前讲解 Docker for Win 和 Docker for Mac 安装的时候,我们提到过这两个软件的配置中都有一块配置 Docker 中默认网络的内容,这块所指的默认网络就是这个 bridge 网络。
$ sudo docker inspect mysql
[
{
## ......
"NetworkSettings": {
## ......
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "bc14eb1da66b67c7d155d6c78cb5389d4ffa6c719c8be3280628b7b54617441b",
"EndpointID": "1e201db6858341d326be4510971b2f81f0f85ebd09b9b168e1df61bab18a6f22",
"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
}
}
## ......
}
## ......
}
]
docker CLI 里与网络相关的命令都以 docker network
开头,其中创建网络的命令是 docker network create
。
$ sudo docker network create -d bridge individual
# docker network create -d bridge testnet
通过 -d
选项我们可以为新的网络指定驱动的类型,其值可以是刚才我们所提及的 bridge、host、overlay、maclan、none,也可以是其他网络驱动插件所定义的类型。这里我们使用的是 Bridge Driver ( 当我们不指定网络驱动时,Docker 也会默认采用 Bridge Driver 作为网络驱动 )。
通过 docker network ls
或是 docker network list
可以查看 Docker 中已经存在的网络。
`$ sudo docker network ls`
`NETWORK ID NAME DRIVER SCOPE`
`bc14eb1da66b bridge bridge local`
`35c3ef1cc27d individual bridge local`
docker network create --driver bridge --subnet 172.17.0.0/16 --gateway 172.17.0.1 yourNetName
,创建自定义网络,指定网络类型、子网范围以及网关地址;
我们通过 docker inspect
观察一下此时的容器网络。
$ sudo docker inspect mysql
[
{
## ......
"NetworkSettings": {
## ......
"Networks": {
"individual": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"2ad678e6d110"
],
"NetworkID": "35c3ef1cc27d24e15a2b22bdd606dc28e58f0593ead6a57da34a8ed989b1b15d",
"EndpointID": "41a2345b913a45c3c5aae258776fcd1be03b812403e249f96b161e50d66595ab",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:12:00:02",
"DriverOpts": null
}
}
## ......
}
## ......
}
]
这时候我们通过 --link
让处于另外一个网络的容器连接到这个容器上,看看会发生什么样的效果。
$ sudo docker run -d --name webapp --link mysql --network bridge webapp:latest
docker: Error response from daemon: Cannot link to /mysql, as it does not belong to the default network.
ERRO[0000] error waiting for container: context canceled
可以看到容器并不能正常的启动,而 Docker 提醒我们两个容器处于不同的网络,之间是不能相互连接引用的。
我们来改变一下,让运行 Web 应用的容器加入到 individual 这个网络,就可以成功建立容器间的网络连接了。
$ sudo docker run -d --name webapp --link mysql --network individual webapp:latest
Docker 安装时,自动在host上创建了如下3个网络bridge、host、none,可以使用 docker inspect查看网络详情, 挂载 none 网络上的容器只有 lo,无法与外界通信,**.**挂在 host 网络上的容器共享宿主机的 network namespace,即容器的网络配置与 host 网络配置完全一样
# docker inspect none
[
{
"Name": "none",
"Id": "8a84fded05e5362b29b80ea97f793528b04c85d78f61de261fa63b34f574d6b6",
"Created": "2022-08-21T08:05:09.923418335Z",
"Scope": "local",
"Driver": "null", #驱动类型
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [] #字段为空
},
...输出省略
docker network connect 网络名称 容器名称
docker network connect testnet tomcat
连接会在容器inspect中看到一个新的网络配置
docker inspect tomcat
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "c987472b617f0b3c069e64e67e577b0bccf1673d13933f4a0f30d1f1aa53e55c",
"EndpointID": "0575bc0f6dcf3b889f64e22933297b6d358edb0a2eef47061e6e79e0bde8d578",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:12:00:02",
"DriverOpts": null
},
"testnet": {
"IPAMConfig": {},
"Links": null,
"Aliases": [
"4691f4df2bc0"
],
"NetworkID": "8bd1730d8426a824c32499baebb3cae39c6403ff43c7c32a66931aae7abb95ff",
"EndpointID": "e1e06afe216d1f6b6b5d832cb95db47471de9fee625c890ce9b2cc85999091fa",
"Gateway": "172.19.0.1",
"IPAddress": "172.19.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:13:00:02",
"DriverOpts": {}
}
docker network inspect 网络名称
docker network disconnect 网络名称 容器名称
docker network prune
docker network rm 网络名称
在实际使用中,还有一个非常常见的需求,就是我们需要在容器外通过网络访问容器中的应用。最简单的一个例子,我们提供了 Web 服务,那么我们就需要提供一种方式访问运行在容器中的 Web 应用。在 Docker 中,提供了一个端口映射的功能实现这样的需求。通过 Docker 端口映射功能,我们可以把容器的端口映射到宿主操作系统的端口上,当我们从外部访问宿主操作系统的端口时,数据请求就会自动发送给与之关联的容器端口。要映射端口,我们可以在创建容器时使用 -p
或者是 --publish
选项。
$ sudo docker run -d --name nginx -p 80:80 -p 443:443 nginx:1.12
使用端口映射选项的格式是 -p
,其中 ip 是宿主操作系统的监听 ip,可以用来控制监听的网卡,默认为 0.0.0.0,也就是监听所有网卡。host-port 和 container-port 分别表示映射到宿主操作系统的端口和容器的端口,这两者是可以不一样的,我们可以将容器的 80 端口映射到宿主操作系统的 8080 端口,传入 -p 8080:80
即可。
器端口是容器里面tomcat的端口号,如果没有修改,就必须写8080.宿主机的端口号可以任意指定。ip写成0.0.0.0的是因为在服务器中,0.0.0.0指的是本机上的所有IPV4地址,是真正表示“本网络中的本机”。 一般我们在服务端绑定端口的时候可以选择绑定到0.0.0.0,这样我的服务访问方就可以通过我的多个ip地址访问我的服务。
我们可以在容器列表里看到端口映射的配置。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc79fc5d42a6 nginx:1.12 "nginx -g 'daemon of…" 4 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx
Docker防火墙通常用于保护Docker容器中的应用程序免遭恶意攻击。防火墙通过过滤流入和流出的网络流量来维护应用程序的安全。在Docker中,防火墙相关的规则都是基于iptables来实现的。因此,使用Docker防火墙之前需要了解iptables的相关知识。另外,在进行内网映射时,我们也要注意容器内部的防火墙,在关闭 Docker 容器的防火墙之前,我们需要先查看 Docker 容器的防火墙状态。可以使用以下命令来查看 Docker 容器的防火墙状态:
docker inspect 容器ID | grep -i iptables
其中,"容器ID"为您要查看防火墙状态的 Docker 容器的ID。
如果输出结果包含以下行,那么 Docker 容器的防火墙是启用的:
"Iptables": true,
"Iptables-Status": "Enabled",
有两种方法可以关闭 Docker 容器的防火墙。
方法一:禁用 Docker 容器的默认 iptables 规则
Docker 容器默认使用 iptables 来管理网络流量,而 iptables 是一个非常强大的防火墙软件。如果您想完全禁用 Docker 容器的防火墙功能,可以禁用默认的 iptables 规则。可以使用以下命令来禁用 Docker 容器的默认 iptables 规则:
docker run --rm --privileged alpine:latest sh -c "echo 'net.ipv4.conf.all.route_localnet=1' >> /etc/sysctl.conf && sysctl -p && iptables -P FORWARD ACCEPT && iptables -F && iptables -X"
该命令将在一个 Alpine 容器中运行一个特定的脚本以禁用 Docker 容器的默认 iptables 规则。该命令会自动清除 Docker 容器的所有 iptables 规则。
方法二:修改 Docker 容器的 iptables 规则
如果您只想关闭 Docker 容器的特定 iptables 规则,可以使用以下命令:
docker exec 容器ID iptables -P INPUT ACCEPT
其中,"容器ID"为您要修改 iptables 规则的 Docker 容器的ID。该命令将允许输入流量,从而关闭 Docker 容器的防火墙。
在docker中后台运行tomct 并将容器命名为tomct ,映射8080对外映射到宿主机8080端口,暴漏tomcat容器8080端口,默认的网络模式为 bridge,不指定网络模式,容器启动默认的网络模式为bridge
docker run -itd --name tomcat -p 0.0.0.0:8080:8080 --expose 8080 tomcat
设置tomcat 容器使用host 网络模式
docker run -d --name tomcat --expose 8080 --network host tomcat
docker network create --driver=bridge --gateway=192.168.137.1 --subnet=192.168.137.0/16 myNet1
docker run --name containerName -p 80:80 -d --network myNet1 myNginx
docker network disconnect myNet1 myNginx
docker network create --driver=bridge --gateway=192.168.137.1 --subnet=192.168.137.0/16 myNet2
# 执行后myNginx容器的网络就变成了myNet2
docker network connect myNet2 myNginx
docker network disconnect myNet2 myNginx
Docker 的端口映射功能是将容器端口映射到宿主操作系统的端口上,实际来说就是映射到了 Linux 系统的端口上。而我们知道,在 Windows 和 macOS 中运行的 Docker,其 Linux 环境是被虚拟出来的,如果我们仅仅是将端口映射到 Linux 上,由于虚拟环境还有一层隔离,我们依然不能通过 Windows 或 macOS 的端口来访问容器。
解决这种问题的方法很简单,只需要再加一次映射,将虚拟 Linux 系统中的端口映射到 Windows 或 macOS 的端口即可。
docker volume COMMAND
操作符 | 释义 | 用法 |
---|---|---|
inspect | 查看详细信息 | docker volume inspect |
ls | 打印已有数据卷 | docker volume ls |
rm | 删除数据卷 | docker volume rm |
prune | 清理无用数据卷 | docker volume prune |
create | 创建卷 | docker volume create |
docker volume ls
,查看所有存在的数据卷信息;
docker volume inspect name
,查看数据卷的详细信息,比如对应主机的路径;
docker volume create name
,创建一个name名称的数据卷,创建的卷的路径在/var/lib/docker/volumes/xxxx/_data 下
docker 数据卷的默认目录为 /var/lib/docker/volumes
docker run -it -v /主机目录:/容器内目录
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个–privileged=true参数
启动起来的时候我们可以通过docker inspect 容器id
默认是可读可写,设置只读限制:容器实例内部被限制,只能读取不能写
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
区别 | 挂载命令 | 查看特定的卷 | 卷名 | 卷在宿主机中位置 |
---|---|---|---|---|
匿名 | -v 只指定容器内路径 |
docker volume inspect 卷名 | 随机 | /var/lib/docker/volumes/xxxx/_data |
具名 [推荐] | -v 卷名:容器内路径 |
docker volume inspect 卷名 | 指定 | /var/lib/docker/volumes/xxxx/_data |
指定路径 | -v 宿主机指定路径:容器内路径 |
- | - | 按指定路径 |
1.创建卷
root@DIGITAL-CAIJ:/home# docker volume create volumetest
volumetest
root@DIGITAL-CAIJ:/home# docker volume ls
DRIVER VOLUME NAME
local volumetest
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest# docker volume inspect volumetest
[
{
"CreatedAt": "2023-08-15T23:46:55+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/volumetest/_data",
"Name": "volumetest",
"Options": null,
"Scope": "local"
}
]
2.挂载卷到容器制定目录
docker run -d -P --name nginx02 -v volumename:/etc/nginx nginx
匿名挂载只指定容器内路径
docker run -d -P --name nginx02 -v /etc/nginx nginx
操作示例
root@DIGITAL-CAIJ:/# docker run -d --name tomcat -p 8080:8080 -v volumetest:/usr/local/tomcat/logs tomcat
245db065242b7493a984d4a48d4c99da82829f7142cf752ccca00ab974d8587b
root@DIGITAL-CAIJ:/# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
245db065242b tomcat "catalina.sh run" 12 seconds ago Up 11 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp tomcat
root@DIGITAL-CAIJ:/# docker volume ls
DRIVER VOLUME NAME
local volumetest
root@DIGITAL-CAIJ:/# docker volume inspect volumetest
[
{
"CreatedAt": "2023-08-15T23:46:55+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/volumetest/_data",
"Name": "volumetest",
"Options": null,
"Scope": "local"
}
]_
root@DIGITAL-CAIJ:/# cd /var/lib/docker/volumes/volumetest/_data
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data# ll
total 16
drwxrwxrwt 2 root root 4096 Aug 16 00:14 ./
drwx-----x 3 root root 4096 Aug 15 23:46 ../
-rw-r----- 1 root root 4628 Aug 16 00:14 catalina.2023-08-15.log
-rw-r----- 1 root root 0 Aug 16 00:14 localhost_access_log.2023-08-15.txt
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data#
文件内容自动同步
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data# docker exec -it tomcat bash
root@245db065242b:/usr/local/tomcat# cd logs/
root@245db065242b:/usr/local/tomcat/logs# touch test.text
root@245db065242b:/usr/local/tomcat/logs# ll
total 20
drwxrwxrwt 2 root root 4096 Aug 15 16:18 ./
drwxr-xr-x 1 root root 4096 Jul 25 23:16 ../
-rw-r----- 1 root root 4628 Aug 15 16:14 catalina.2023-08-15.log
-rw-r----- 1 root root 0 Aug 15 16:14 localhost_access_log.2023-08-15.txt
-rw-r--r-- 1 root root 0 Aug 15 16:18 test.text
root@245db065242b:/usr/local/tomcat/logs# exit
exit
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data# ll
total 16
drwxrwxrwt 2 root root 4096 Aug 16 00:18 ./
drwx-----x 3 root root 4096 Aug 15 23:46 ../
-rw-r----- 1 root root 4628 Aug 16 00:14 catalina.2023-08-15.log
-rw-r----- 1 root root 0 Aug 16 00:14 localhost_access_log.2023-08-15.txt
-rw-r--r-- 1 root root 0 Aug 16 00:18 test.text
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data# ls /home/avic/
snap
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data# docker run -d --name tomcat -p 8080:8080 -v /home/avic/:/usr/local/tomcat/logs tomcat
68d546cee691a7239950a2a7d0efe751c190de36bdcbf4b74d5524ff0602c219
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data# ls /home/avic/
catalina.2023-08-15.log localhost_access_log.2023-08-15.txt snap
root@DIGITAL-CAIJ:/var/lib/docker/volumes/volumetest/_data#