Apakah mungkin untuk memulai sesi shell dalam wadah berjalan (tanpa ssh)

341

Saya secara naif mengharapkan perintah ini untuk menjalankan bash shell dalam wadah yang sedang berjalan:

docker run "id of running container" /bin/bash

sepertinya itu tidak mungkin, saya mendapatkan kesalahan:

2013/07/27 20:00:24 Internal server error: 404 trying to fetch remote history for 27d757283842

Jadi, jika saya ingin menjalankan bash shell dalam wadah yang sedang berjalan (mis. Untuk tujuan diagnosis)

apakah saya harus menjalankan server SSH di dalamnya dan masuk melalui ssh?

Max L.
sumber
1
docker run CONTAINERdirencanakan pada 1.0
kolypto
7
Sejak docker 1.3 Anda harus benar-benar melakukan seperti yang dijelaskan pada jawaban ini
Thomasleveil
1
hanyadocker attach container_name
maxbellec
1
Sepertinya jawaban kedua jauh lebih baik saat ini daripada yang diterima - bisakah Anda mempertimbangkan kembali untuk mengubah jawaban yang diterima?
jsbueno

Jawaban:

285

EDIT: Sekarang Anda dapat menggunakan docker exec -it "id of running container" bash( doc )

Sebelumnya, jawaban untuk pertanyaan ini adalah:

Jika Anda benar-benar harus dan Anda berada dalam lingkungan debug, Anda dapat melakukan ini: sudo lxc-attach -n <ID> Perhatikan bahwa id harus penuh ( docker ps -notrunc).

Namun, saya sangat merekomendasikan ini.

pemberitahuan: -notruncsudah usang, itu akan segera diganti --no-trunc.

creack
sumber
1
mengapa Anda merekomendasikannya?
Max L.
7
Saya merekomendasikan untuk tidak melakukannya karena 1) membutuhkan kernel yang sangat baru, 2) Anda melakukan hal-hal di luar buruh pelabuhan sehingga Anda tidak akan dapat melacaknya (log, melampirkan, dll). Juga, buruh pelabuhan mungkin menggunakan lxc sekarang, tetapi tidak ada garansi itu akan melakukannya selamanya.
Creack
1
Coba perbarui ke 0.7.6. Docker masih menggunakan lxc sekarang dan lxc-attachseharusnya berfungsi dengan baik. Saya hanya dua kali lipat diperiksa dan berfungsi untuk saya. (Perhatikan bahwa ini tidak akan berfungsi dengan kernel 3.8 sebelumnya).
Celah
2
per 0,9 buruh pelabuhan tidak lagi berjalan dengan LXC secara default. Anda harus meluncurkan buruh pelabuhan deamon dengandocker -d -e lxc
kevzettler
2
Max L., use case Anda dapat diatasi dengan volume data . Tidak diuji contoh: 1) menjalankan wadah dengan log nginx volume data yang: docker run -v /var/log/nginx -name somename imagename command; 2) menjalankan wadah lain untuk melihat konten data volume: docker run -volumes-from somename -i -t busybox /bin/sh.
ciastek
615

Dengan docker 1.3, ada perintah baru docker exec. Ini memungkinkan Anda untuk memasuki buruh pelabuhan:

docker exec -it "id of running container" bash
Michael_Scharf
sumber
2
Ini bekerja baik untuk saya. Tambahan yang sangat membantu untuk menjalankan buruh pelabuhan.
oraserrata
Bagaimana jika saya melakukan perubahan saat menjalankan wadah yang sedang berjalan dan ingin mencerminkan perubahan secara online? apa praktik terbaik?
mediaroot
Sangat berguna. Terima kasih
luongnv89
gunakan docker psuntuk mendapatkan id menjalankan instance
muon
Catatan: Wadah mungkin tidak memiliki bash (»exec:" bash ": file yang dapat dieksekusi tidak ditemukan«). Gunakan docker inspect <image>untuk melihat cangkang apa yang tersedia. Misalnya lari docker exec -it <container id> /bin/shsaja.
pixelbrackets
14

Kerjakan saja

docker attach container_name

Seperti yang disebutkan dalam komentar, untuk melepaskan dari wadah tanpa menghentikannya, ketikkan Ctrlpkemudian Ctrlq.

maxbellec
sumber
5
Terima kasih!! Itu membantu. Dan dalam konteks pertanyaan aktual, saya ingin menambahkan sesuatu. Setelah debugging wadah kami menggunakan, docker attach container_namegunakan ctrl pdan ctrl qbukannya exit. exitperintah menghentikan wadah, di mana ctrlpdan ctrl qhanya melepaskan wadah itu dan tetap berjalan
phoenix
10

Karena banyak hal yang menyakitkan, saat ini cara yang disarankan untuk mengakses wadah yang sedang berjalan adalah menggunakan nsenter.

Anda dapat menemukan informasi lebih lanjut tentang repositori github ini . Tetapi secara umum Anda dapat menggunakan nsenter seperti ini:

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

atau Anda dapat menggunakan pembungkus docker-enter:

docker-enter <container_name_or_ID>

Penjelasan yang bagus tentang topik ini dapat ditemukan di entri blog Jérôme Petazzoni: Mengapa Anda tidak perlu menjalankan sshd di wadah buruh pelabuhan Anda

Teudimundo
sumber
sayangnya, variabel env kacau menggunakan pendekatan ini (jika Anda ingin memeriksa variabel yang dibuat oleh tautan). Saya sarankan melakukan source /proc/*/environ.
Tomas Tomecek
8

Hal pertama yang tidak bisa Anda jalankan

docker run "existing container" command

Karena perintah ini mengharapkan gambar dan bukan wadah dan itu akan tetap menghasilkan wadah baru (jadi bukan yang Anda ingin lihat)

Saya setuju dengan fakta bahwa dengan buruh pelabuhan kita harus mendorong diri kita sendiri untuk berpikir dengan cara yang berbeda (jadi Anda harus menemukan cara agar Anda tidak perlu masuk ke dalam wadah), tetapi saya masih menganggapnya berguna dan ini adalah cara saya bekerja di sekitarnya.

Saya menjalankan perintah saya melalui penyelia dalam mode DEAMON.

Lalu saya melakukan apa yang saya sebut docker_loop.sh Konten cukup banyak ini:

#!/bin/bash
/usr/bin/supervisord
/usr/bin/supervisorctl
while ( true )
    do
    echo "Detach with Ctrl-p Ctrl-q. Dropping to shell"
    sleep 1
    /bin/bash
done

Apa yang dilakukannya adalah memungkinkan Anda untuk "melampirkan" ke wadah dan disajikan dengan supervisorctlantarmuka untuk menghentikan / memulai / memulai kembali dan memeriksa log. Jika itu tidak cukup, Anda dapat Ctrl+Ddan Anda akan jatuh ke dalam shell yang akan memungkinkan Anda untuk mengintip seolah-olah itu adalah sistem normal.

HARAP JUGA MENGAMBIL KE ACCOUNT bahwa sistem ini tidak seaman memiliki wadah tanpa cangkang, jadi ambil semua langkah yang diperlukan untuk mengamankan wadah Anda.

Alessandro
sumber
5

Mengawasi permintaan penarikan ini: https://github.com/docker/docker/pull/7409

Yang mengimplementasikan yang akan datang docker exec <container_id> <command> utilitas yang . Ketika ini tersedia, seharusnya dimungkinkan untuk memulai dan menghentikan layanan ssh di dalam wadah yang sedang berjalan.

Ada juga yang nsinitharus dilakukan ini: "nsinit menyediakan cara praktis untuk mengakses shell di dalam namespace yang dijalankan penampung" , tetapi tampaknya sulit untuk dijalankan. https://gist.github.com/ubergarm/ed42ebbea293350c30a6

teman
sumber
docker execmendarat di Docker 1.3, jadi sekarang mungkin untuk membuat dan bergabung dengan sesi shell baru dalam wadah yang sedang berjalan
foz
3

Kamu bisa menggunakan

docker exec -it <container_name> bash
antikytheraton
sumber
1

Sebenarnya ada cara untuk memiliki shell di wadah.

Anggaplah Anda /root/run.shmeluncurkan proses, manajer proses (penyelia), atau apa pun.

Buat /root/runme.shdengan beberapa trik layar gnu:

# Spawn a screen with two tabs
screen -AdmS 'main' /root/run.sh
screen -S 'main' -X screen bash -l
screen -r 'main'

Sekarang, Anda memiliki daemon di tab 0, dan shell interaktif di tab 1. docker attachkapan saja untuk melihat apa yang terjadi di dalam wadah.

Saran lain adalah membuat gambar "bundel pengembangan" di atas gambar produksi dengan semua alat yang diperlukan, termasuk trik layar ini.

kolypto
sumber
1

ini solusinya

bagian dari DOckerfile:

...
RUN mkdir -p /opt
ADD initd.sh /opt/
RUN chmod +x /opt/initd.sh
ENTRYPOINT ["/opt/initd.sh"]

bagian dari "initd.sh"

#!/bin/bash
...
/etc/init.d/gearman-job-server start
/etc/init.d/supervisor start
#very important!!!
/bin/bash

setelah gambar dibangun, Anda memiliki dua opsi menggunakan exec dan melampirkan:

  1. dengan exec (yang saya gunakan), jalankan:

docker run --name $ CONTAINER_NAME -dt $ IMAGE_NAME

kemudian

docker exec -itu $ CONTAINER_NAME / bin / bash

dan gunakan

CTRL + D untuk melepaskan

  1. dengan melampirkan, jalankan:

docker run --name $ CONTAINER_NAME -dit $ IMAGE_NAME

kemudian

buruh pelabuhan melampirkan $ CONTAINER_NAME

dan gunakan

CTRL + P dan CTRL + Q untuk melepaskan

perbedaan antara opsi ada di parameter -i

tim
sumber
1

Ada dua cara.

Dengan melampirkan

$ sudo docker attach 665b4a1e17b6 #by ID

Dengan exec

$ sudo docker exec - -t 665b4a1e17b6 #by ID
gurubelli
sumber
0

Ini berguna memberi nama saat menjalankan wadah. Anda tidak perlu merujuk container_id.

docker run --name container_name yourimage docker exec -it container_name bash

Matsumoto Kazuya
sumber
0

pertama, dapatkan id wadah dari wadah yang diinginkan oleh

docker ps

Anda akan mendapatkan sesuatu seperti ini:

CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                          PORTS                    NAMES
3ac548b6b315        frontend_react-web     "npm run start"     48 seconds ago      Up 47 seconds                   0.0.0.0:3000->3000/tcp   frontend_react-web_1

sekarang salin id wadah ini dan jalankan perintah berikut:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh

Umesh
sumber
-2

Mungkin Anda menyesatkan seperti saya untuk berpikir dalam hal VM ketika mengembangkan wadah. Saran saya: Cobalah untuk tidak melakukannya.

Kontainer sama seperti proses lainnya. Memang Anda mungkin ingin "melampirkan" padanya untuk keperluan debugging (pikirkan / proc // env atau strace -p) tetapi itu adalah kasus yang sangat khusus.

Biasanya Anda hanya "menjalankan" prosesnya, jadi jika Anda ingin mengubah konfigurasi atau membaca log, cukup buat wadah baru dan pastikan Anda menulis log di luarnya dengan membagikan direktori, menulis ke stdout (jadi buruh pelabuhan bekerja) atau semacam itu.

Untuk keperluan debugging Anda mungkin ingin memulai sebuah shell, lalu kode Anda, lalu tekan CTRL-p + CTRL-q untuk membiarkan shell tetap utuh. Dengan cara ini Anda dapat memasang kembali menggunakan:

docker attach <container_id>

Jika Anda ingin men-debug wadah karena melakukan sesuatu yang tidak Anda harapkan, coba debug itu: /server/596994/how-can-i-debug-a-docker-container - inisialisasi

estani
sumber
Ini sepenuhnya salah. Mampu mengintrospeksi namespace LXC di mana aplikasi Anda berjalan bukanlah "kasus yang sangat istimewa", itu adalah kegiatan umum / harian untuk pengembang apa pun.
sleepycal
@sleepycal "pengembang apa pun" terdengar sedikit bias. Bagaimanapun saya menggunakan introspeksi proses sehingga hal yang sama berlaku untuk wadah. Itulah ide di balik debugging. Anda melampirkan debugger ke proses (yang mungkin memiliki cli). Berpikir bahwa Anda "sedang" masuk ke dalam wadah itu kedengarannya masih menyesatkan bagi saya.
estani
-4

Tidak, ini tidak mungkin. Gunakan sesuatu seperti supervisorduntuk mendapatkan server ssh jika itu diperlukan. Meskipun, saya pasti mempertanyakan kebutuhan.

Nick Stinemates
sumber