如何在Docker容器内运行命令?
在Docker容器内运行命令比你想象的要简单。
Docker容器是一个隔离的环境,通常包含一个单独的应用程序及其所有所需的依赖项。很多时候,我们需要在一个docker container内运行一些命令。有几种方法可以在容器内执行命令并获取所需的输出。
让我们看看如何做到。
使用交互式Shell
我们可以直接访问容器的Shell,并像在普通Linux终端中一样执行我们的命令。要获取一个已停止(不在运行状态)容器的交互式Shell,可以使用以下命令:
$ docker run -it ubuntu bash
root@c520631f652d:/#
正如你所看到的,我们直接进入了一个新的Ubuntu
容器,在这里我们可以运行我们的命令。如果容器已经在运行,你可以使用下面的exec
命令。
首先,让我们找出容器ID。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c2d969adde7a nginx "/docker-entrypoint.…" 2 hours ago Up 2 hours 127.0.0.1:80->80/tcp nginx
0960560bc24b mariadb "docker-entrypoint.s…" 2 hours ago Up 2 hours 127.0.0.1:3306->3306/tcp mariadb
然后,进入容器ID为c2d969adde7a的容器。
$ docker exec -it c2d969adde7a bash
root@c2d969adde7a:/#
在上面的输出中,你可以观察到我们启动了一个正在运行状态的nginx
容器的bash
会话。在这里,我们可以执行任何受支持的命令并获得输出。
注意 – 你的容器可能没有bash,如果是这样的话,你可以使用sh。
例如:
docker exec -it c2d969adde7a sh
直接输出
通常,我们只需要一个或两个命令的输出,而不需要一个完整的交互式会话来完成我们的任务。你可以在容器内运行所需的命令,并直接获取其输出,而无需打开一个新的Shell会话,使用exec
命令而不使用-it
标志。其语法如下:
$ docker exec
这里有一个例子:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c2d969adde7a nginx "/docker-entrypoint.…" 2 hours ago Up 2 hours 127.0.0.1:80->80/tcp nginx
0960560bc24b mariadb "docker-entrypoint.s…" 2 hours ago Up 2 hours 127.0.0.1:3306->3306/tcp mariadb
$ docker exec 0960560bc24b ps -ef | grep mysql
mysql 1 0 0 13:35 ? 00:00:02 mysqld
$
我们在运行的MariaDB容器中执行了ps -ef | grep mysql
命令,并直接获得了输出。
Dockerfile方式
这不是你可以在一个docker container内运行命令的确切方式,尽管它可能在开发环境或初始部署调试等情况下有所帮助。我们可以在Dockerfile中使用RUN
命令。下面是我们的示例Dockerfile:
FROM nginx:latest
RUN nginx -V
它简单地从注册表中拉取最新的nginx
镜像,然后在构建镜像时运行nginx -V
命令来显示Nginx版本。
$ docker build -t nginx-test .
正在发送上下文到 Docker 守护程序 2.048KB
步骤 1/2 : FROM nginx:latest
---> 7ce4f91ef623
步骤 2/2 : RUN nginx -V
---> Running in 43918bbbeaa5
nginx 版本: nginx/1.19.9
由 gcc 8.3.0 (Debian 8.3.0-6) 编译
使用 OpenSSL 1.1.1d 10 Sep 2019
启用 TLS SNI 支持
配置参数: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.9/debian/debuild-base/nginx-1.19.9=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
正在移除中间容器 43918bbbeaa5
---> d682277f2e50
成功构建了 d682277f2e50
成功标记为 nginx-test:latest
$
观察以上代码段中 RUN
命令的输出。以上代码段将只在第一次构建时显示,并且后续构建将不会重复显示 RUN
命令的输出。作为解决方法,您可以尝试使用 --no-cache
标志:
$ docker build -t nginx-test . --no-cache
最后一种方法不是最好的方法,但有时在调试等方面可能会有帮助。
总结
在 Docker 中运行命令是简单的,有几种可用的方法。这是 Docker 管理员的常规任务,因此了解这些命令是有用的。
接下来,学习一些流行的 Docker commands。