此处将为大家介绍关于如何正确使用dockerrun-i、-t、-d参数的详细内容,并且为您解答有关dockerrun参数详解的相关问题,此外,我们还将为您介绍关于167dockerdocker构建ng
此处将为大家介绍关于如何正确使用 docker run -i、 -t、-d 参数的详细内容,并且为您解答有关docker run 参数详解的相关问题,此外,我们还将为您介绍关于167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo、Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock、docker run 和 docker-compose 参数对照关系、docker run和docker container run之间有什么区别的有用信息。
本文目录一览:- 如何正确使用 docker run -i、 -t、-d 参数(docker run 参数详解)
- 167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo
- Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock
- docker run 和 docker-compose 参数对照关系
- docker run和docker container run之间有什么区别
如何正确使用 docker run -i、 -t、-d 参数(docker run 参数详解)
在使用 docker run
的时候,我们经常会使用到 -i、-t
和 -d
参数,那么这几个参数的作用究竟是什么呢,这篇文章就来简单分析一下。
选项说明
官方文档对这几个选项的说明如下:
--interactive , -i Keep STDIN open even if not attached
--tty , -t Allocate a pseudo-TTY
--detach , -d Run container in background and print container ID
-d
是--detach
的简写,它的作用是在后台运行容器,并且打印容器 id-t
是--tty
的简写,它的作用是分配一个伪 TTY-i
是--interactive
的简写,它的作用是即使没有 attached,也要保持 STDIN 打开状态
对于官方的解释,表示只有 -d
参数看明白了,其余两个参数的解释还是有点过于简单。伪TTY
、STDIN
是什么,甚至这个 attach
很多文章翻译成连接
准确吗?我们没有具备一些操作系统的底层知识,对这些还是一脸懵逼的。
那么,我们就先讲一下我们能看懂的这个 -d
选项吧。
detach 选项
大多数情况下,我们都是希望 Docker 能够在后台运行容器,而不是直接在宿主机上与之交互。如果不加 -d
选项,容器会在宿主机终端运行,并把输出的结果(STDOUT)打印到宿主机上面。
使用 -d
选项后,容器会在后台执行并输出容器 ID。我们可以使用 docker logs [container]
来查看容器的输出结果。如果想跟容器进行交互,可以使用 docker exec -it [container] /bin/bash
来操作。
需要注意的是,容器是否会持久运行,和
-d
选项无关。关于这一点,在 docker run 如何让容器启动后不会自动停止这篇文章中也有介绍。
interactive 选项
选项详解
-i
选项根据文档的解释就比较费解了,我们不妨先看另外一个选项 -a
。
--attach , -a Attach to STDIN, STDOUT or STDERR
它的意思是 把宿主机标准输入,输出和错误流(也就是 STDIN
, STDOUT
和 STDERR
)附加到容器。
在 Linux 中,STDIN
是标准的输入流,通常对应终端的键盘;STDOUT
是标准输出流,STDERR
是标准错误输出流,它们都对应终端的屏幕。进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。关于这方面的更多了解可以参照 What Are stdin, stdout, and stderr on Linux? 这篇文章。
那么我们再来看 -i
的解释:Keep STDIN open even if not attached
。
Keep STDIN open
也就是说让容器的标准输入保持打开状态,even if not attached
强调的是即使没有把宿主机标准输入,输出和错误流附加到容器依然保持容器的标准输入为打开状态。
很多人比较费解的都是后半句,其实它只是一个强调作用。在 Docker run reference 中有一段提到如果没有指定 -a
选项,默认会 attach stdout 和 stderr。
那么我们可以做一个小实验。下面的语句是通过管道把宿主机的 echo test
命令执行的结果作为 node
容器的输入,在容器中执行 cat
命令再通过 stdout
输出到宿主机。可以看到打印出 test。
echo test | docker run --rm --name node -a stdin -a stdout -i node:12.18.3-slim cat
接下来我们不使用 -a
选项,得到的也是一样的结果。
echo test | docker run --rm --name node -i node:12.18.3-slim cat
这也就是说,如果加了 -i
选项,容器的 STDIN
就会一直保持打开,我们就可以以交互模式(interactive mode)来运行容器了。
交互模式
我们可以让容器运行后执行一条命令,比如前面提到的 cat
,看一下会发生什么:
docker run --rm --name node -i node:12.18.3-slim cat
可以看到,我们能够在宿主机上跟容器进行交互了,它会输出我们输入的结果。那么我们也可以运行 /bin/bash
来启动一个 shell
docker run --rm --name node -i node:12.18.3-slim /bin/bash
如果我们执行的是一个持续与容器交互的程序,容器的状态就会一直保持运行状态。那么我们想结束掉与容器的交互呢?
在 docker attach 命令里有介绍到,使用 CTRL-c
可以让容器停止运行,它是通过发送一个 STGKILL
信号来实现的。
但是我们尝试一下发现并不行,这是因为 Linux 1 号进程的特殊性。不过,我们可以通过 CTRL-d
去停止容器,因为它不是发送一个信号,而是表示一个特殊的二进制值 EOF
其实这里又涉及到了几个 Linux 的知识点:
- Linux PID 1(Linux 的 1 号进程)
- Linux 的信号(SIGINT、SIGTERM、SIGQUIT、SIGKILL、SIGHUP)
- EOF
如果想让 CTRL-c
也可以生效,我们可以在 docker run
命令加上 --init
选项
docker run --rm --init --name node -i node:12.18.3-slim /bin/bash
对上面提到的几个知识做了一定了解后,我们再来看直接通过 -i
启动一个容器而不执行命令会发生什么。
docker run --rm --name node -i node:12.18.3-slim
可以看到容器正常启动并保持运行,我们在宿主机的终端输入任何字符都没有反应。
我们可以再开启另外一个终端,进入容器看一下 1 号进程,发现是 node
$ docker exec -it node /bin/bash
$ ps -aux
所以我们可以得出一个结论:如果容器启动的 1 号进程是一个 shell 程序的话,我们通过 -i
选项就可以与之交互,保持容器持续运行。不指定 -i
,容器启动后就会自动退出。
现在还有一个问题就是,如果只指定了 -i
选项,我们在宿主机终端输入任何字符都没有反应。这个问题,我们可以用 -t
来解决,所以接下来就介绍一下 -t
选项的作用了。
tty 选项
如果对 Linux 的 TTY 比较熟悉的话,对于这个选项就比较了解了。我们可以把它理解为 Linux 的终端程序,所以 -t
选项就可以理解为为容器分配一个伪 tty 终端并绑定到容器的标准输入上,之后用户就可以通过终端来控制容器了。
一般 -t
都是与 -i
一起出现的,也就是 -it
。在讲这个之前,我们先单独分析一下 -t
吧。
我们首先试一下运行容器后执行一个交互命令,看与 -i
的区别是什么:
docker run --rm --name node -t node:12.18.3-slim cat
执行完后,容器也可以持续运行。与单独指定 -i
不一样的是,在终端中输入任何字符都没有反应;CTRL-d
终止不了容器;直接关闭宿主机的终端,容器还继续保持运行。
我们来解释一下执行的结果为什么是这样的。首先,输入任何字符都没有反应,是因为容器没有打开标准输入,我们输入的任何字符都是没有传递进容器的。所以 cat
一直会在等待永远不会到来的输入,也就一直保持容器运行状态。CTRL-d
同样也不会传递到容器,直接关闭宿主机的终端也是同样的道理,因为它是在容器内部分配了一个伪终端。所以,我们关闭宿主机的终端后,开启一个新的终端输入 docker ps
,可以看到容器仍然在运行。
通过 -t
选项直接运行一个容器也是一样的结果。
docker run --rm --name node -t node:12.18.3-slim
我们可以看到与 -i
不同的是,它会使用伪终端进入到 node 的 shell 中,但是我们输入任何字符都是没用的。关闭宿主机的终端后,容器依然运行。
这也就解释了为什么容器启动的 1 号进程是一个 shell 程序的话,我们使用 -dt
就可以保持容器持续在后台运行。
-it
前面我们知道了如果直接执行 docker run
,它默认会有 stdout 流,如果我们加了 -i
,它会保持 stdin 流打开。那么,我们再加上 -t
选项,就是说标准输入变成了一个伪 tty 终端。从这里也可以看出,交互模式下单独指定 -t
选项是没有意义的,因为如果容器的标准输入没有打开,我们是输入不了任何内容的。
简单来说,指定 -t
而不指定 -i
,意味着在容器里开启了一个伪终端,但是我们的输入并不会传递到伪终端的输入。
所以,官方文档也写到了,在交互模式下,-i
与 -t
选项必须结合使用,也就是 -it
。
那么,我们使用 -it
选项来启动一个容器,看一下有哪些变化:
docker run --rm --name node -it node:12.18.3-slim
我们进入了 node 的 shell,并且可以使用快捷键 Tab 来显示信息。
也可以通过 CTRL-c
来退出交互模式。
参考:
- What''s the difference between ^C and ^D for UNIX/Mac OS X terminal?
- Avoid running Node.js as PID 1 under Docker images
- Linux 命令中 Ctrl+z、Ctrl+c 和 Ctrl+d
- linux 的 0 号进程 和 1 号进程
- Termination-Signals
- Linux 的伪终端的基本原理 及其在远程登录(SSH,telnet 等)中的应用
- What is a TTY on Linux? (and How to Use the tty Command)
- What does “the input device is not a TTY” exactly mean in “docker run” output?
- Confused about Docker -t option to Allocate a pseudo-TTY
167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo
background : 最近为小伙伴们筹划docker系列的技术分享,研究了一会docker相关技术, 在此记录一下构建nginx容器时候的坑
1.nginx服务器根目录问题
docker 官方镜像提供的nginx基于debian/jessie平台,其文件结构和ubuntu中的nginx中并不相同
eg:
run一个niginx容器
<span>//80端口被占用,so...</span> $ sudo docker run <span>-it</span><span>-p</span><span>800</span>:<span>800</span> nginx $ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES <span>1801</span>a32aab54 nginx <span>"nginx -g ''daemon off"</span><span>2</span> minutes ago Up <span>2</span> minutes <span>80</span>/tcp, <span>443</span>/tcp, <span>0.0</span><span>.0</span><span>.0</span>:<span>800</span><span>-></span><span>800</span>/tcp berserk_kare
进入容器内部
<span>$ </span>sudo docker exec -it <span>1801</span>a32aab54 /bin/bash root<span>@1801a32aab54</span><span>:/</span><span># </span>
查看nginx目录
<span># cd /etc/nginx/</span> conf<span>.d</span>/ koi-utf mime<span>.types</span> nginx<span>.conf</span> uwsgi_params fastcgi_params koi-win modules/ scgi_params win-utf
可以看到不仅没有熟悉的 /sites-available,也没有 /sites-enabled
继续查看nginx配置
<span># cat /conf.d/default.conf</span><span>server</span> { listen <span>80</span>; server_name localhost; <span>#charset koi8-r;</span><span>#access_log /var/log/nginx/log/host.access.log main;</span> location / { root /usr/share/nginx/html; <span>index</span><span>index</span>.html <span>index</span>.htm; } <span>#error_page 404 /404.html;</span><span># redirect server error pages to the static page /50x.html</span><span>#</span> error_page <span>500</span><span>502</span><span>503</span><span>504</span> /<span>50</span>x.html; location = /<span>50</span>x.html { root /usr/share/nginx/html; } <span>#...省略php-fpm配置,好长..</span> }
根目录配置: root /usr/share/nginx/html;
测试
<span># cd /usr/share/nginx/html</span><span># touch index.html</span><span># echo "test nginx in docker" >index.html</span>
php-fpm配置相关
'').addClass(''pre-numbering'').hide(); $(this).addClass(''has-numbering'').parent().append($numbering); for (i = 1; i '').text(i)); }; $numbering.fadeIn(1700); }); });以上就介绍了167 docker docker构建nginx容器系列问题,包括了docker,nginx方面的内容,希望对PHP教程有兴趣的朋友有所帮助。
Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock
在 Docker 容器里面使用 docker run
/docker build
?
Docker 容器技术目前是微服务/持续集成/持续交付领域的第一选择。而在 DevOps 中,我们需要将各种后端/前端的测试/构建环境打包成 Docker 镜像,然后在需要的时候,Jenkins 会使用这些镜像启动容器以执行 Jenkins 任务。
为了方便维护,我们的 CI 系统如 Jenkins,也会使用 Docker 方式部署。 Jenkins 任务中有些任务需要将微服务构建成 Docker 镜像,然后推送到 Harbor 私有仓库中。 或者我们所有的 Jenkins Master 镜像和 Jenkins Slave 镜像本身都不包含任何额外的构建环境,执行任务时都需要启动包含对应环境的镜像来执行任务。
我们的 Jenkins Master、Jenkins Slaves 都是跑在容器里面的,该如何在这些容器里面调用 docker run
命令启动包含 CI 环境的镜像呢? 在这些 CI 镜像里面,我们从源码编译完成后,又如何通过 docker build
将编译结果打包成 Docker 镜像,然后推送到内网仓库呢?
答案下面揭晓。
一、原理说明:/var/run/docker.sock
Docker 采取的是 Client/Server 架构,我们常用的 docker xxx
命令工具,只是 docker 的 client,我们通过该命令行执行命令时,实际上是在通过 client 与 docker engine 通信。
我们通过 apt/yum 安装 docker-ce 时,会自动生成一个 systemd 的 service,所以安装完成后,需要通过 sudo systemctl enable docker.service
来启用该服务。 这个 Docker 服务启动的,就是 docker engine,查看 /usr/lib/systemd/system/docker.service
,能看到有这样一条语句:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
默认情况下,Docker守护进程会生成一个 socket(/var/run/docker.sock
)文件来进行本地进程通信,因此只能在本地使用 docker 客户端或者使用 Docker API 进行操作。 sock 文件是 UNIX 域套接字,它可以通过文件系统(而非网络地址)进行寻址和访问。
因此只要以数据卷的形式将 docker 客户端和上述 socket 套接字挂载到容器内部,就能实现 "Docker in Docker",在容器内使用 docker 命令了。具体的命令见后面的「示例」部分。
要记住的是,真正执行我们的 docker 命令的是 docker engine,而这个 engine 跑在宿主机上。所以这并不是真正的 "Docker in Docker".
二、示例
在容器内部使用宿主机的 docker,方法有二:
- 命令行方式:将
/usr/bin/docker
映射进容器内部,然后直接在容器内部使用这个命令行工具docker
- 需要的时候,也可以将
/etc/docker
文件夹映射到容器内,这样容器内的docker
命令行工具也会使用与宿主机同样的配置。
- 需要的时候,也可以将
- 编程方式:在容器内部以编程的方式使用 docker
- 通过 python 使用 docker: 在 Dockerfile 中通过
pip install docker
将 docker client 安装到镜像中来使用
- 通过 python 使用 docker: 在 Dockerfile 中通过
容器的启动方式也有两种,如下:
1. 直接通过 docker 命令启动
示例命令如下:
docker run --name <name> \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
--user root \
<image-name>:<tag>
**必须以 root 用户启动!(或者其他有权限读写 /var/run/docker.sock
的用户)**然后,在容器内就能正常使用 docker 命令,或者访问宿主机的 docker api 了。
2. 使用 docker-compose 启动
docker-compose.yml 文件内容如下:
version: ''3.3''
services:
jenkins-master:
image: jenkinsci/blueocean:latest
container_name: jenkins-master
environment:
- TZ=Asia/Shanghai # 时区
ports:
- "8080:8080"
- "50000:50000"
volumes:
- ./jenkins_home:/var/jenkins_home # 将容器中的数据映射到宿主机
- /usr/bin/docker:/usr/bin/docker # 为容器内部提供 docker 命令行工具(这个随意)
- /var/run/docker.sock:/var/run/docker.sock # 容器内部通过 unix socket 使用宿主机 docker engine
user: root # 必须确保容器以 root 用户启动!(这样它才有权限读写 docker.socket)
restart: always
然后通过 docker-compose up -d
即可后台启动容器。
Docker 中的 uid 与 gid
通过上面的操作,我们在容器内执行 docker ps
时,还是很可能会遇到一个问题:权限问题。
如果你容器的默认用户是 root,那么你不会遇到这个问题,因为 /var/run/docker.sock
的 onwer 就是 root.
但是一般来说,为了限制用户的权限,容器的默认用户一般都是 uid 和 gid 都是 1000 的普通用户。这样我们就没有权限访问 /var/run/docker.sock
了。
解决办法:
方法一(不一定有效):在构建镜像时,最后一层添加如下内容:
# docker 用户组的 id,通常都是 999
RUN groupadd -g 999 docker \
&& usermod -aG docker <your_user_name>
这样我们的默认用户,就能使用 docker 命令了。
P.S.
999
不一定是 docker 用户组,所以上述方法某些情况下可能失效。这时还是老老实实通过docker run -u root
启动容器吧。(或者在docker-compose.yml
中添加user: root
属性)
参考
- Docker in Docker - 王柏元
docker run 和 docker-compose 参数对照关系
在实际工作中大部分时候会使用 docker-compose,但有时候为了方便为了快捷会直接 docker run。这里记录一下 docker-compose 和 docker run 命令的一些参数对照关系,后面就比较方便对 docker run 的改成 docker-compose 就方便管理和查看了。
docker run
docker run \
-p 80:80 -p 3000 \
-v "/root/aaa.txt:/var/run/aaa.txt" -v "/root/data:/data" \
-m 500M --memory-reservation 200M \
--cpu-period=50000 --cpu-quota=25000 \
-e "EmailServer=192.168.0.1" \
--add-host=otherhost:192.168.0.2 \
--net=host \
--restart=always \
--dns=8.8.8.8 \
--log-driver=json-file --log-opt max-size=200k --log-opt max-file=10 \
--name=mynginx \
--hostname nginxhost \
-d nginx:latest sleep 10000
docker-compose
version: "3.7"
services:
db:
image: nginx:latest
volumes:
- "/root/aaa.txt:/var/run/aaa.txt"
- "/root/data:/data"
ports:
- "80:80"
- "3000"
deploy:
resources:
limits:
cpus: ''0.50''
memory: 500M
reservations:
cpus: ''0.25''
memory: 200M
environment:
Server: 192.168.0.1
extra_hosts:
- "otherhost:192.168.0.2"
- "otherhost:192.168.0.3"
network_mode: "host"
restart: always
dns: 8.8.8.8
command: /bin/bash -c "sleep 10000"
logging:
driver: json-file
options:
max-size: "200k" # 单个文件大小为200k
max-file: "10" # 最多10个文件
container_name: mynginx
hostname: nginxhost
healthcheck: #docker-compose有,docker run没有
test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
interval: 1m30s # 设置检测间隔
timeout: 10s # 设置检测超时时间
retries: 3 # 设置重试次数
start_period: 40s # 启动后,多少秒开始启动检测程序
docker run和docker container run之间有什么区别
任何人都可以帮助我理解docker run& docker container运行?
当我做docker run –help& docker container run –help from docker cmd line.我看到以下内容
在新容器中运行命令.
它们如何在内部运行容器或两者在同一工作中是否相同?
根据https://forums.docker.com/t/docker-run-and-docker-container-run/30526. docker run仍然是旧版本,很快就会被弃用,但未确认.
在docker 1.13之前,docker run命令仅可用.然后将cli命令重构为具有docker COMMAND SUBCOMMAND的表单,在这种情况下,COMMAND是容器并且运行SUBCOMMAND.这样做是为了具有更多的原位组合命令,因为当时的命令数量已经大大增加.
您可以在CLI restructured下阅读更多内容.
简而言之,使用docker容器运行,因为它是运行容器的更现代的方式.
我们今天的关于如何正确使用 docker run -i、 -t、-d 参数和docker run 参数详解的分享已经告一段落,感谢您的关注,如果您想了解更多关于167 docker docker构建nginx容器系列问题 docker registry docker run docker toolbo、Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock、docker run 和 docker-compose 参数对照关系、docker run和docker container run之间有什么区别的相关信息,请在本站查询。
本文标签: