SSH เข้า Docker ได้อย่างไร?


90

ฉันต้องการสร้างขั้นตอนโครงสร้างพื้นฐานต่อไปนี้:

จะทำได้อย่างไรโดยใช้ Docker?

คำตอบ:


70

ประการแรกคุณต้องติดตั้งเซิร์ฟเวอร์ SSH ในภาพที่คุณต้องการ ssh-into คุณสามารถใช้อิมเมจพื้นฐานสำหรับคอนเทนเนอร์ทั้งหมดของคุณโดยติดตั้งเซิร์ฟเวอร์ ssh จากนั้นคุณจะต้องรันคอนเทนเนอร์แต่ละตัวที่แมปพอร์ต ssh (ค่าเริ่มต้น 22) กับพอร์ตหนึ่งไปยังพอร์ตของโฮสต์ (เซิร์ฟเวอร์ระยะไกลในรูปภาพของคุณ) โดยใช้-p <hostPort>:<containerPort>. กล่าวคือ:

docker run -p 52022:22 container1 
docker run -p 53022:22 container2

แล้วถ้าพอร์ต 52022 และ 53022 ของโฮสต์สามารถเข้าถึงได้จากภายนอกคุณโดยตรงสามารถ ssh ตู้คอนเทนเนอร์โดยใช้ IP ของโฮสต์ (เซิร์ฟเวอร์ระยะไกล) ระบุในพอร์ต SSH -p <port>กับ ได้แก่ :

ssh -p 52022 myuser@RemoteServer -> SSH ไปยังคอนเทนเนอร์ 1

ssh -p 53022 myuser@RemoteServer -> SSH ไปยังคอนเทนเนอร์ 2


และจะเปิดเผยท่าเรือเหล่านี้สู่โลกภายนอกได้อย่างไร? ฉันหมายความว่ามีความเป็นไปได้ที่จะกำหนดค่าโดยไม่ใช้ nginx หรือไม่?
Kamil Lelonek

2
@squixy: เป็นเพียงพอร์ตบนโฮสต์ของคุณ เพียงแค่เปิดเผยในลักษณะเดียวกับแอปพลิเคชันอื่น ๆ มันอาจใช้งานได้หรือคุณอาจต้องเปิดพอร์ตในไฟร์วอลล์ของคุณ
Adrian Mouat

ฉันเข้าใจแล้วฉันแค่สงสัยว่าวิธีที่ดีที่สุดในการแมปชื่อโดเมนกับพอร์ตคืออะไร แต่ฉันเชื่อว่า NginX เป็นโซลูชันที่ฉันสามารถนำไปใช้ได้อย่างง่ายดาย
Kamil Lelonek

container1 คืออะไร? เมื่อฉันทำ "นักเทียบท่ารัน <ชื่อ>" <ชื่อ> จะถูกตีความเป็นชื่อรูปภาพดังนั้นนักเทียบท่าจึงมองหารูปภาพใน repos ID คอนเทนเนอร์ของฉันใช้ไม่ได้กับการรันนักเทียบท่า ฉันใช้ "docker start <containerID>" เพื่อเริ่มคอนเทนเนอร์ แต่ docker start ไม่ยอมรับพารามิเตอร์ -p
mvmn

1
หากผู้ใช้ Docker เป็น "root" คุณจะต้องให้รหัสผ่านแก่ผู้ใช้ root ผ่าน "passwd root" นอกจากนี้ฉันพบว่ามันใช้งานได้: นักเทียบท่าวิ่ง -p 52022: 22 container1 service ssh start -D FOREGROUND
CMP

42

หมายเหตุ : คำตอบนี้ส่งเสริมเครื่องมือที่ฉันเขียน

คำตอบที่เลือกในที่นี้แนะนำให้ติดตั้งเซิร์ฟเวอร์ SSH ลงในทุกอิมเมจ แนวคิดนี้ไม่ใช่แนวทางที่ถูกต้อง ( https://docs.docker.com/articles/dockerfile_best-practices/ )

ฉันได้สร้างเซิร์ฟเวอร์ SSH ที่มีคอนเทนเนอร์ซึ่งคุณสามารถ 'ยึดติด' กับคอนเทนเนอร์ที่กำลังทำงานอยู่ ด้วยวิธีนี้คุณสามารถสร้างองค์ประกอบในทุกคอนเทนเนอร์ ข้อกำหนดเพียงอย่างเดียวคือภาชนะที่มีการทุบตี

ตัวอย่างต่อไปนี้จะเริ่มต้นเซิร์ฟเวอร์ SSH ที่เปิดเผยบนพอร์ต 2222 ของเครื่องโลคัล

$ 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 -p 2222 localhost

สำหรับคำแนะนำและเอกสารเพิ่มเติมโปรดดู: https://github.com/jeroenpeeters/docker-ssh

สิ่งนี้ไม่เพียงเอาชนะแนวคิดของหนึ่งกระบวนการต่อคอนเทนเนอร์ แต่ยังเป็นวิธีการที่ยุ่งยากเมื่อใช้รูปภาพจาก Docker Hub เนื่องจากมักไม่มี (และไม่ควร) มีเซิร์ฟเวอร์ SSH


6
นี่น่าจะเป็นคำตอบที่ถูกต้อง การติดตั้งเซิร์ฟเวอร์ SSH ในทุกอิมเมจที่คุณต้องการจะขัดกับเกรนของนักเทียบท่า คุณควรมีบริการเดียวต่อคอนเทนเนอร์และควรเขียนแอปพลิเคชันจากบริการ / คอนเทนเนอร์
babbata

2
@JeroenPeeters ฉันเดาว่าสิ่งที่จำเป็นต้องมีอีกอย่างคือ "ซ็อกเก็ต Docker ถูกแมปลงในคอนเทนเนอร์ซึ่งจะช่วยให้คอนเทนเนอร์เข้าถึง Docker Engine ได้"
Nam G VU

1
'jeroenpeeters' ในคำสั่งด้านบนคืออะไร? เป็นชื่อผู้ใช้บนคอนเทนเนอร์หรือไม่
Pratik Patil

1
@PratikPatil เป็นส่วนหนึ่งของชื่อภาพ hub.docker.com/r/jeroenpeeters/docker-ssh
Jeroen Peeters

13

ไฟล์เหล่านี้จะเปิด sshd และเรียกใช้บริการได้สำเร็จเพื่อให้คุณสามารถ ssh ในเครื่องได้ (คุณใช้ Cyberduck ไม่ใช่เหรอ?)

Dockerfile

FROM swiftdocker/swift
MAINTAINER Nobody

RUN apt-get update && apt-get -y install openssh-server supervisor
RUN mkdir /var/run/sshd
RUN echo 'root:password' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

EXPOSE 22
CMD ["/usr/bin/supervisord"]

Supervisor.conf

[supervisord]
nodaemon=true

[program:sshd]
command=/usr/sbin/sshd -D

เพื่อสร้าง / รัน start daemon / กระโดดเข้าเชลล์

docker build -t swift3-ssh .  
docker run -p 2222:22 -i -t swift3-ssh
docker ps # find container id
docker exec -i -t <containerid> /bin/bash

ป้อนคำอธิบายภาพที่นี่


2
สวัสดีคำตอบที่ดี คอนเทนเนอร์ของฉันปรากฏขึ้นและแจ้งให้ฉันเข้าสู่ระบบ แต่ข้อมูลประจำตัวคือ "root" และ "password" หรือไม่? ดูเหมือนจะไม่ได้ผลสำหรับฉัน แต่ฉันชอบวิธีแก้ปัญหาของคุณและฉันต้องการใช้มัน
Jabari Dash

ไม่แน่ใจ - ฉันประสบปัญหาในการกดปุ่มพอร์ต 22 - ตรวจสอบให้แน่ใจว่าคุณใช้พอร์ต 2222 บ่อยครั้งที่อาจมีการเปิดสิ่งต่างๆบนอุปกรณ์ท้องถิ่นเพื่อขัดแย้งกับพอร์ตนั้น
johndpope

บรรทัดนี้ ('PermitRootLogin without-password') ใน / etc / ssh / sshd_config จะแสดงความคิดเห็นตามค่าเริ่มต้นดังนั้นให้ใช้ 's / # PermitRootLogin without-password / PermitRootLogin ใช่ /' แทน คุณอาจต้องใช้ 'ห้าม - รหัสผ่าน' แทน 'ไม่มีรหัสผ่าน' สำหรับ Ubuntu 16.04+ คุณสามารถดำเนินการในคอนเทนเนอร์เพื่อตรวจสอบล่วงหน้าได้
ItsJack

10

ฉันเดาว่ามันเป็นไปได้ คุณต้องติดตั้งเซิร์ฟเวอร์ SSH ในแต่ละคอนเทนเนอร์และแสดงพอร์ตบนโฮสต์ สิ่งที่น่ารำคาญหลักคือการรักษา / จดจำการแมปพอร์ตไปยังคอนเทนเนอร์

อย่างไรก็ตามฉันต้องตั้งคำถามว่าทำไมคุณถึงต้องการทำสิ่งนี้ SSH'ng ในคอนเทนเนอร์ควรหายากพอที่จะไม่ยุ่งยากในการ ssh ไปยังโฮสต์จากนั้นใช้ docker exec เพื่อเข้าไปในคอนเทนเนอร์


ดังนั้นฉันต้องการจำลองสภาพแวดล้อมของฉันในแบบที่ฉันสร้างคอนเทนเนอร์ต่อโปรเจ็กต์ ดังนั้นแต่ละโครงการจึงมีสภาพแวดล้อมผู้ใช้ฐานข้อมูลเวอร์ชัน python / ruby ​​และอื่น ๆ เป็นของตัวเอง ฉันต้องการแยกโครงการโดยไม่ต้องสร้างเซิร์ฟเวอร์หลายเครื่อง
Kamil Lelonek

1
@squixy; ตกลง. โดยปกติคอนเทนเนอร์นักเทียบท่าจะมีกระบวนการเดียวเท่านั้น - โดยนัยคุณควรมีคอนเทนเนอร์แยกต่างหากสำหรับ mysql, php และ apache ฉันไม่แน่ใจว่าจะได้ผลดีแค่ไหนสำหรับคุณ
Adrian Mouat

ฉันรู้คุณรู้วิธีแก้ปัญหาที่ดีกว่าสำหรับกรณีของฉันหรือไม่?
Kamil Lelonek

1
@squixy มันขึ้นอยู่กับหลายสิ่งหลายอย่าง ฉันอยากจะแนะนำให้แบ่งแต่ละคอนเทนเนอร์ออกเป็นหลาย ๆ คอนเทนเนอร์ คุณต้องการ ssh เพื่ออะไร? หากเป็นเพียงการบำรุงรักษาทำไมคุณไม่สามารถเข้าสู่โฮสต์ได้แล้ว docker exec? คำถามใหญ่เกินไปที่จะตอบในความคิดเห็นที่ฉันกลัว
Adrian Mouat

ตามที่เอเดรียนเขียนเมื่อคุณเริ่มใช้ Docker คุณจะรู้ว่า container! = virtual machine แทบจะไม่จำเป็นต้องเข้าถึงคอนเทนเนอร์แบบโต้ตอบ
mzedeler

8

สร้างภาพนักเทียบท่าด้วยการopenssh-serverติดตั้งล่วงหน้า:

Dockerfile

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

สร้างภาพโดยใช้:

$ docker build -t eg_sshd .

เรียกใช้test_sshdคอนเทนเนอร์:

$ docker run -d -P --name test_sshd eg_sshd
$ docker port test_sshd 22

0.0.0.0:49154

ส่งไปยังคอนเทนเนอร์ของคุณ:

$ ssh root@192.168.1.2 -p 49154
# The password is ``screencast``.
root@f38c87f2a42d:/#

ที่มา: https://docs.docker.com/engine/examples/running_ssh_service/#build-an-eg_sshd-image


เป็นสิ่งที่ควรค่าแก่การพูดถึงว่าสำหรับ mac os x คุณสามารถลองssh root@localhost -p <ssh_host_port>ทำตามคำแนะนำได้ที่นี่
Claudio Santos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.