我如何进入Docker容器的shell?

时间:2015-05-11 16:12:31

标签: docker docker-container

我开始使用Docker了。我正在使用WordPress基本图像和docker-compose。

我正在尝试ssh到其中一个容器中来检查在初始构建期间创建的文件/目录。我试图运行docker-compose run containername ls -la,但这没有做任何事情。即使它确实如此,我宁愿有一个控制台,我可以遍历目录结构,而不是运行单个命令。使用Docker执行此操作的正确方法是什么?

25 个答案:

答案 0 :(得分:1260)

docker attach将允许您连接到Docker容器,但这与ssh不同。例如,如果您的容器正在运行Web服务器,docker attach可能会将您连接到Web服务器进程的 stdout 。它不一定会给你一个shell。

docker exec命令可能就是你要找的;这将允许您在现有容器中运行任意命令。例如:

docker exec -it <mycontainer> bash

当然,您运行的任何命令都必须存在于容器文件系统中。

在上面的命令<mycontainer>中是目标容器的名称或ID。你是否使用docker compose并不重要;只需运行docker ps并使用ID(第一列中显示的十六进制字符串)或名称(显示在最后一列中)。例如,给出:

$ docker ps
d2d4a89aaee9        larsks/mini-httpd   "mini_httpd -d /cont   7 days ago          Up 7 days                               web                 

我可以跑:

$ docker exec -it web ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
18: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:3/64 scope link 
       valid_lft forever preferred_lft forever

我可以通过运行来完成同样的事情:

$ docker exec -it d2d4a89aaee9 ip addr

同样,我可以在容器中启动shell;

$ docker exec -it web sh
/ # echo This is inside the container.
This is inside the container.
/ # exit
$

答案 1 :(得分:247)

要打入正在运行的容器,请输入:

docker exec -t -i container_name /bin/bash

答案 2 :(得分:71)

让我们说,由于您自己的原因,您确实想要使用SSH。它需要几个步骤,但它可以完成。以下是您将在容器内运行以设置它的命令...

apt-get update
apt-get install openssh-server

mkdir /var/run/sshd
chmod 0755 /var/run/sshd
/usr/sbin/sshd

useradd --create-home --shell /bin/bash --groups sudo username ## includes 'sudo'
passwd username ## Enter a password

apt-get install x11-apps ## X11 demo applications (optional)
ifconfig | awk '/inet addr/{print substr($2,6)}' ## Display IP address (optional)

现在,您甚至可以使用X11转发到SSH客户端来运行图形应用程序(如果它们安装在容器中):

ssh -X username@IPADDRESS
xeyes ## run an X11 demo app in the client

以下是一些相关资源:

答案 3 :(得分:20)

注意:这个答案推广了我写过的工具。

我已经创建了一个容器化的SSH服务器,您可以“粘贴”任何正在运行的容器。这样您就可以为每个容器创建合成。唯一的要求是容器有Bash。

以下示例将启动连接到名为“my-container”的容器的SSH服务器。

docker run -d -p 2222:22 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e CONTAINER=my-container -e AUTH_MECHANISM=noAuth \
  jeroenpeeters/docker-ssh

ssh localhost -p 2222

当您连接到此SSH服务(使用您选择的SSH客户端)时,将在名为“my-container”的容器中启动Bash会话。

有关更多指示和文档,请参阅:https://github.com/jeroenpeeters/docker-ssh

答案 4 :(得分:14)

使用此命令将SSH连接到Docker容器中:

sudo docker exec -i -t (container ID) bash

答案 5 :(得分:13)

如果你在Windows上使用Docker并希望获得对容器的shell访问权限,请使用:

winpty docker exec -it <container_id> sh

最有可能的是,您已经安装了Git Bash如果您不这样做,请确保安装它。

答案 6 :(得分:7)

如果容器已经退出(可能是由于某些错误),则可以

$ docker run --rm -it --entrypoint /bin/ash image_name

$ docker run --rm -it --entrypoint /bin/sh image_name

$ docker run --rm -it --entrypoint /bin/bash image_name

创建一个新容器并放入一个外壳。由于您指定了--rm,因此退出外壳程序时将删除该容器。

答案 7 :(得分:7)

在某些情况下,您的图片可能是基于阿尔卑斯山的。在这种情况下,它将抛出:

  

OCI运行时exec失败:exec失败:container_linux.go:348:启动   容器进程导致“exec:\”bash \“:找不到可执行文件   $ PATH“:未知

因为/bin/bash不存在。而不是这个你应该使用:

docker exec -it 9f7d99aa6625 ash

docker exec -it 9f7d99aa6625 sh

答案 8 :(得分:7)

GOINSIDE SOLUTION

安装goinside命令行工具:

sudo npm install -g goinside

然后进入具有正确终端大小的docker容器:

goinside docker_container_name

旧答案

我们已将此代码段放在~/.profile

goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside

这不仅使每个人都能够进入正在运行的容器:

goinside containername

它也解决了长寿problem about fixed Docker container terminal sizes。如果你面对它,那会非常烦人。

此外,如果您关注the link,您的Docker容器名称也将完成命令。

答案 9 :(得分:7)

要连接到Windows容器中的cmd,请使用

docker exec -it d8c25fde2769 cmd

d8c25fde2769 是容器ID。

答案 10 :(得分:6)

很简单

列出所有Docker映像:

sudo docker images

在我的系统上,它显示以下输出:

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
bash                latest              922b9cc3ea5e        9 hours ago
14.03 MB
ubuntu              latest              7feff7652c69        5 weeks ago         81.15 MB

我的PC上有两个Docker映像。假设我要运行第一个。

sudo docker run -i -t ubuntu:latest /bin/bash

这将使您可以对容器进行终端控制。现在,您可以在容器内执行所有类型的Shell操作。像执行ls一样,将在文件系统根目录中输出所有文件夹。

bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

答案 11 :(得分:5)

使用此命令:

docker exec -it containerid /bin/bash

答案 12 :(得分:4)

要检查文件,请运行docker run -it <image> /bin/bash以获取交互式终端。可以通过docker images获取图像列表。与docker exec相反,此解决方案也适用于图像未启动(或在运行后立即退出)的情况​​。

答案 13 :(得分:4)

使用:

docker attach <container name/id here>

另一种方式,虽然存在危险,但是使用attach,但如果你 Ctrl + C 退出会话,你也将停止容器。如果您只想查看发生的情况,请使用docker logs -f

:~$ docker attach --help
Usage:  docker attach [OPTIONS] CONTAINER

Attach to a running container

Options:
      --detach-keys string   Override the key sequence for detaching a container
      --help                 Print usage
      --no-stdin             Do not attach STDIN
      --sig-proxy            Proxy all received signals to the process (default true)

答案 14 :(得分:4)

docker exec肯定是一个解决方案。处理您提出的问题的一种简单方法是将Docker中的目录挂载到本地系统的目录

这样您就可以立即查看本地路径中的更改。

docker run -v /Users/<path>:/<container path> 

答案 15 :(得分:3)

要执行到名为// Constructor public BlogRecyclerViewAdapter(Context context, List<Blog> blogList) { this.context = context; this.blogList = blogList; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.post_row, parent, false); return new ViewHolder(view, context); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { // Now bind the views and the data Blog blog = blogList.get(position); String imageUrl = null; holder.title.setText(blog.getTitle()); holder.desc.setText(blog.getDesc()); DateFormat dateFormat = DateFormat.getDateInstance(); String formattedDate = dateFormat.format(new Date(Long.valueOf(blog.getTimeStamp())).getTime()); holder.timeStamp.setText(formattedDate); imageUrl = blog.getImage(); //TODO: Use Picasso library to load image Picasso.get().load(imageUrl).into(holder.image); } @Override public int getItemCount() { return blogList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public TextView title; public TextView desc; public TextView timeStamp; public ImageView image; String userId; public ViewHolder(@NonNull View view, Context ctx) { super(view); context = ctx; title = (TextView) view.findViewById(R.id.postTitleList); desc = (TextView) view.findViewById(R.id.postTextList); image = (ImageView) view.findViewById(R.id.postImageList); timeStamp = (TextView) view.findViewById(R.id.timeStampList); userId = null; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // We can go to the next activity } }); } } 的运行容器中,请执行以下命令

如果容器具有test外壳

bash

如果容器具有docker exec -it test /bin/bash 外壳并且大多数情况下都存在

bourne

答案 16 :(得分:3)

如果您使用Kitematic安装了Docker,则可以使用GUI。从Docker图标打开Kitematic,在Kitematic窗口中选择您的容器,然后点击exec图标。

您也可以在此GUI中查看容器日志和大量容器信息(在设置选项卡中)。

Select Kitematic from menu

Click on exec

答案 17 :(得分:1)

您可以通过传递选项-ti与Docker容器中的终端进行交互

docker run --rm -ti <image-name>
eg: docker run --rm -ti ubuntu

-t代表终端 -i代表互动

答案 18 :(得分:1)

就我而言,由于某些原因,我需要检查每个容器中所有与网络有关的信息。因此,以下命令在容器中必须有效...

ip
route
netstat
ps
...

我检查了所有这些答案,没有一个对我有帮助。我在其他网站上搜索了信息。我不会在此处添加超级链接,因为它不是用英语编写的。因此,我只为与我有相同要求的人员提供了摘要解决方案。

假设您有一个名为light-test的运行容器。请按照以下步骤操作。

  • docker inspect light-test -f {{.NetworkSettings.SandboxKey}}。该命令将得到类似于/var/run/docker/netns/xxxx的回复。
  • 然后ln -s /var/run/docker/netns/xxxx /var/run/netns/xxxx。该目录可能不存在,请先执行mkdir /var/run/netns
  • 现在,您可以执行ip netns exec xxxx ip addr show来探索容器中的网络世界。

PS。 xxxx始终是从第一个命令接收到的相同值。当然,任何其他命令都有效,即ip netns exec xxxx netstat -antp|grep 8080

答案 19 :(得分:0)

根据目标,至少有两个选项。

选项1:创建一个新的bash进程并将其加入(更简单)

  • 示例开始:docker exec -it <containername> /bin/bash
  • 退出:输入exit
  • Pro:适用于所有容器(不取决于CMD / Entrypoint)
  • 相反:使用自己的会话和自己的环境变量创建一个新进程

选项2:附加到已经运行的bash (更好)

  • 示例开始:docker attach --detach-keys ctrl-d <containername>
  • 退出:使用键ctrld
  • Pro:加入与容器中完全相同的运行bash。您拥有相同的会话和相同的环境变量。
  • 相反:仅当CMD / Entrypoint是CMD ["/bin/bash"]CMD ["/bin/bash", "--init-file", "myfile.sh"] AND 的交互式bash时有效,并且如果容器已使用docker run -itd <image>这样的交互式选项启动, -i =交互式,-t = tty和-d = deamon [opt])

我们发现选项2更有用。例如,我们将apache2-foreground更改为正常背景apache2,然后开始运行bash

答案 20 :(得分:0)

我创建了一个终端功能,以更轻松地访问容器的终端。也许对你们也有用:

结果是,而不是键入:

docker exec -it [container_id] /bin/bash

您将写:

dbash [container_id]

将以下内容放入〜/ .bash_profile(或其他适用于您的内容)中,然后打开一个新的终端窗口并享受快捷方式:

#usage: dbash [container_id]
dbash() {
    docker exec -it "$1" /bin/bash
}

答案 21 :(得分:0)

如果您使用的是Docker Compose,那么这将带您进入Docker容器。

docker-compose run container_name /bin/bash

在容器内部,它将带您到Dockerfile中定义的WORKDIR。您可以通过

更改工作目录
WORKDIR directory_path # E.g  /usr/src -> container's path

答案 22 :(得分:0)

Map<String, Long> map = list.stream().collect(
        Collectors.groupingBy(Company::getCompany, 
                              Collectors.mapping((Company c) -> c, Collectors.counting())));

或者取决于外壳,可以是

$ docker exec -it <Container-Id> /bin/bash

您可以通过$ docker exec -it <Container-Id> /bin/sh 命令获取容器ID

docker ps =互动式

-i =分配伪TTY

答案 23 :(得分:0)

另一种选择是使用nsenter

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid

答案 24 :(得分:-3)

对于docker-compose up(Docker4Drupal)

docker-compose exec php bash

我在Linux笔记本电脑上使用Docker for Drupal。运行容器后,我使用&#39; docker-compose exec php bash&#39;与容器连接所以我可以运行drush突击队。它对我来说很好。