
![]()
Bu yazıda özetle bir docker konteynerden diğerine ssh (container to container ssh) ile bağlanma örneği yapacağız.
İş hayatında sık sık bir uzak linux sunucuya bağlanıyoruz. Bu bağlantı için SSH protokolünü kullanıyoruz. Teknik olarak SSH (Secure Shell), bir ağ üzerinden iki bilgisayar arasında güvenli bir şekilde veri alışverişi ve uzaktan oturum açma imkanı sağlayan bir kriptografik protokoldür. Peki Docker ortamında demo, POC, eğitim vb. amaçlarla konteynerler arasında SSH bağlantısı yapmak gerekirse bunu nasıl yapacağız. Normal bir linux işletim sistemi üzerinde ssh sunucusu kurmak ayarlamak ve ona bağlanmak kolay ve bununla ilgili bir çok doküman veya makale var. Benim ihtiyacım oldu ve pek bir kaynak bulamadım. Bu ihtiyacımı çözdüm ve benim gibi insanlar için nasıl çözdüğümü bu yazıda paylaşacağım.
İki tane konteyner olacak. İlki jenkins, ikincisi bir rockylinux konteyner (prod_server).

Kendimize çalışma klasörü yaratalım ve içinde docker-compose.yaml dosyasını oluşturalım.
(base) [train@localhost ~]$ mkdir blog_ssh (base) [train@localhost ~]$ cd blog_ssh/ (base) [train@localhost blog_ssh]$ touch docker-compose.yaml
compose dosyası
version: '3.7'
services:
jenkins:
restart: always
build: ./jenkins
image: jenkins_server
container_name: jenkins
ports:
- "8080:8080"
- "50000:50000"
volumes:
- jenkins_home:/var/jenkins_home
- "/var/run/docker.sock:/var/run/docker.sock"
prod_server:
build: ./prod
image: prod_server
container_name: prod_server
hostname: prod_server
privileged: true
ports:
- "8000:8000"
- "2222:22"
security_opt:
- seccomp:unconfined
tmpfs:
- /run
- /run/lock
volumes:
- ./prod/home/.ssh:/home/prod_user/.ssh
- /sys/fs/cgroup:/sys/fs/cgroup:ro
volumes:
jenkins_home:Yukarıdaki prod_server servisi ayarlarından önemli olanları açıklayalım:
build: ./prod
- Bu ayar,
prod_serverimajını oluşturmak için kullanılacak Dockerfile’ın bulunduğu dizini belirtir. Bu durumda, Dockerfile,prodadlı bir dizin içinde yer almaktadır.
- Bu ayar,
privileged: true
- Bu ayar, konteynere ana bilgisayar sisteminde normalde kısıtlanmış işlemleri gerçekleştirme yetkisi verir. Bu, örneğin Docker içinde Docker çalıştırmak veya bazı düşük seviyeli sistem ayarlarını değiştirmek gibi durumlarda gerekli olabilir. Ancak, güvenlik risklerini artırabileceğinden dikkatli kullanılmalıdır.
security_opt:
- seccomp:unconfined: Konteyner üzerindeki Seccomp güvenlik profilini devre dışı bırakır. Bu, bazı özel durumlarda gerekli olabilir, ancak genellikle güvenlik risklerini artırabileceğinden önerilmez.
tmpfs:
/runve/run/lock: Bu dizinleri geçici bir dosya sistemi (tmpfs) olarak bağlar. Bu, konteynerin performansını artırabilir, ancak konteyner yeniden başlatıldığında bu dizinlerdeki veriler kaybolur.
volumes:
./prod/home/.ssh:/home/prod_user/.ssh: Ana bilgisayardaki./prod/home/.sshdizinini, konteyner içindeki/home/prod_user/.sshdizinine bağlar. Bu, SSH anahtarları gibi önemli dosyaları konteyner içinde kalıcı hale getirmek için kullanılır./sys/fs/cgroup:/sys/fs/cgroup:ro: Ana bilgisayardaki cgroup dosya sistemini, konteyner içinde salt okunur olarak bağlar. Bu, konteynerin kaynak kullanımını kontrol etmek için gereklidir.
Özgün Dockerfile’lar.
- jenkins
mkdir jenkins cat<<EOF | tee jenkins/Dockerfile FROM jenkins/jenkins:lts-jdk17 USER root # Install ansible RUN apt update && \ apt -y install python3-distutils && \ apt -y install python3-apt && \ apt -y install python3 && \ apt -y install iputils-ping netcat-traditional RUN apt-get install -y python3-pip RUN pip install -U ansible --break-system-packages RUN apt-get -y install rsync USER jenkins EOF
FROM jenkins/jenkins:lts-jdk17- Bu satır, Docker imajının temelini belirler.
jenkins/jenkins:lts-jdk17imajını kullanarak, Jenkins’in uzun süreli destek (LTS) sürümünü ve OpenJDK 17’yi içeren bir temel imaj oluşturulur.
- Bu satır, Docker imajının temelini belirler.
USER root- Docker imajının içindeki kullanıcıyı
rootkullanıcısına geçirir. Bu, sonraki adımlarda yönetici ayrıcalıkları gerektiren işlemleri gerçekleştirmek için gereklidir.
- Docker imajının içindeki kullanıcıyı
RUN apt update && \ apt -y install python3-distutils && \ apt -y install python3-apt && \ apt -y install python3 && \ apt -y install iputils-ping netcat-traditional- Bu blok, birkaç paketin kurulumunu gerçekleştirir:
apt update: Paket listelerini günceller.apt -y install ...: Aşağıdaki paketleri yükler:python3-distutils: Python 3 için dağıtım yardımcı programları sağlar.python3-apt: Python 3 için APT (Advanced Package Tool) kitaplığını sağlar.python3: Python 3 yorumlayıcısını yükler.iputils-ping:pingkomutunu sağlar, ağ bağlantısını test etmek için kullanılır.netcat-traditional:nc(netcat) komutunu sağlar, TCP/UDP bağlantıları açmak ve veri göndermek/almak için kullanılır.
- Bu blok, birkaç paketin kurulumunu gerçekleştirir:
RUN apt-get install -y python3-pip- Python 3 için
pippaket yöneticisini yükler.pip, Python paketlerini kurmak ve yönetmek için kullanılır.
- Python 3 için
RUN pip install -U ansible --break-system-packages- Ansible’ı yükler veya günceller.
--break-system-packagesseçeneği, Ansible’ın bağımlılıklarını yüklerken sistem paketleriyle çakışmaları çözmek için kullanılır.
- Ansible’ı yükler veya günceller.
RUN apt-get -y install rsyncrsynckomutunu yükler.rsync, dosyaları ve dizinleri uzak veya yerel sistemler arasında verimli bir şekilde senkronize etmek için kullanılır.
USER jenkins- Kullanıcıyı tekrar
jenkinskullanıcısına geçirir. Bu, Jenkins işlemlerininjenkinskullanıcısı altında çalışmasını sağlar, güvenlik açısından iyi bir uygulamadır.
- Kullanıcıyı tekrar
- prod_server
mkdir prod
cat<<EOF |tee prod/Dockerfile
FROM rockylinux:8.6
ENV container docker
RUN yum -y update && yum clean all
RUN yum -y install openssh-server python3 sudo passwd systemd
RUN adduser -m prod_user && \
echo "Ankara06" | passwd prod_user --stdin && \
usermod -aG wheel prod_user && \
mkdir /home/prod_user/.ssh && \
chown prod_user:prod_user -R /home/prod_user/ && \
chmod 700 /home/prod_user/.ssh
RUN echo "%wheel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
RUN echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
RUN systemctl enable sshd.service
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
COPY init_script.sh /etc/init.d/
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
EOFFROM rockylinux:8.6:- Bu Dockerfile, Rocky Linux 8.6 sürümünü temel alarak bir imaj oluşturur. Temel imaj, işletim sistemi ve temel araçları içerir.
ENV container docker:containeradında bir ortam değişkeni oluşturur ve değerinidockerolarak ayarlar. Bu değişken, konteynerin bir Docker konteyneri olduğunu belirtmek için kullanılabilir.
RUN yum -y update && yum clean all:- Sistem paketlerini günceller (
yum -y update) ve ardından eski paketleri ve önbellekleri temizler (yum clean all).
- Sistem paketlerini günceller (
RUN yum -y install openssh-server python3 sudo passwd systemd:- Gerekli paketleri yükler:
openssh-server: SSH sunucusunu kurar, böylece konteyner uzaktan SSH bağlantılarına izin verir.python3: Python 3 yorumlayıcısını kurar.sudo:sudokomutunu sağlar, kullanıcıların belirli komutları yönetici ayrıcalıklarıyla çalıştırmasına izin verir.passwd: Kullanıcı parolalarını yönetmek içinpasswdkomutunu sağlar.systemd: Sistem ve servis yönetimi için systemd’yi kurar.
- Gerekli paketleri yükler:
RUN adduser -m prod_user && \ echo "Ankara06" | passwd prod_user --stdin && \ usermod -aG wheel prod_user && \ mkdir /home/prod_user/.ssh && \ chown prod_user:prod_user -R /home/prod_user/ && \ chmod 700 /home/prod_user/.ssh:1. github.comgithub.comprod_useradında yeni bir kullanıcı oluşturur ve ona bir ev dizini (-m) atar.- Kullanıcının parolasını “Ankara06” olarak ayarlar.
- Kullanıcıyı
wheelgrubuna ekler, böylecesudokullanarak yönetici ayrıcalıklarıyla komutlar çalıştırabilir. /home/prod_user/.sshdizinini oluşturur ve sahipliğiniprod_userkullanıcısına verir./home/prod_user/dizininin sahipliğini ve izinlerini ayarlar, böylece sadeceprod_usererişebilir./home/prod_user/.sshdizininin izinlerini ayarlar, böylece sadece sahibi okuma, yazma ve yürütme yapabilir.
RUN echo "%wheel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers:wheelgrubundaki kullanıcıların parola sorulmadansudokullanarak herhangi bir komutu çalıştırmasına izin verir. Bu, otomatikleştirilmiş görevler için kullanışlı olabilir, ancak güvenlik risklerini artırabilir, bu nedenle dikkatli kullanılmalıdır.
RUN echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config:- SSH sunucusunun yapılandırma dosyasına
PasswordAuthentication yessatırını ekler. Bu, SSH bağlantılarında parola tabanlı kimlik doğrulamayı etkinleştirir.
- SSH sunucusunun yapılandırma dosyasına
RUN systemctl enable sshd.service:- SSH sunucusunu sistem başlangıcında otomatik olarak başlatacak şekilde ayarlar.
RUN (cd /lib/systemd/system/sysi ...sytemd çalışması için gerekli dosyaları konteyner içinden kaldırır.COPY init_script.sh /etc/init.d/:init_script.shadlı bir dosyayı ana bilgisayardan konteyner içindeki/etc/init.d/dizinine kopyalar. Bu betik, muhtemelen konteyner başlatıldığında bazı ek başlatma görevlerini gerçekleştirir.
VOLUME [ "/sys/fs/cgroup" ]:- Konteyner içindeki
/sys/fs/cgroupdizinini bir volume olarak tanımlar. Bu, ana bilgisayarın cgroup dosya sistemine erişim sağlar, bu da konteynerin kaynak kullanımını kontrol etmek için önemlidir.
- Konteyner içindeki
CMD ["/usr/sbin/init"]:- Konteyner başlatıldığında çalıştırılacak varsayılan komutu belirtir.
/usr/sbin/init, systemd’yi başlatır ve sistemin önyükleme işlemini tamamlar.
- Konteyner başlatıldığında çalıştırılacak varsayılan komutu belirtir.
prod_server ayağa kalkınca sshd servisini çalıştıracak ve bir dosyayı silecek script’i oluşturalım. Bunu Dockerfile içinde de görebiliyorsunuz.
- init_script.sh
cat<<EOF | tee init_script.sh #!/bin/bash systemctl start sshd sleep 3 rm -f /run/nologin # Execute the original CMD exec "$@" EOF
Bu script imaj içine gömülür ve konteyner ayağa kaltıktan sonra /etc/init.d/init_script.sh olarak hazır olur. Konteyner çalışırken bu script çalışında sshd servisi çalışacaktır.
Nihai olarak dosya ve dizin yapısını bir görelim.
tree
.
├── docker-compose.yaml
├── init_script.sh
├── jenkins
│ └── Dockerfile
└── prod
├── Dockerfile
└── init_script.sh
3 directories, 5 filesWindows dosya sisteminde kaydedildikten sonra sh dosyalarında bazı arızalar olabiliyor. Onları düzeltelim her ihtimale karşı ve çalıştırılabilir (executable) yapalım.
chmod +x prod/init_script.sh sed -i 's/\r$//' prod/init_script.sh
Ortamı ayağa kaldırma
docker-compose up --build -d
prod_server volume için şuanki kullanıcımıza (train) yetki verelim.
sudo chown train:train -R prod/home/
prod_server sshd servisini çalıştırma. Bunu konteyner içine gönderdiğimiz init_script.sh ile yapacağız.
docker exec -it prod_server /etc/init.d/init_script.sh
sshd çalışmış mı kontrol edelim.
docker exec -it prod_server systemctl status sshd
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled; vendor preset: enabled)
Active: active (running) since Thu 2024-08-22 03:45:02 UTC; 54s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 88 (sshd)
Tasks: 1 (limit: 24102)
Memory: 1.7M
CGroup: /docker/ed3ff6abc5eeae345c731e8a8c308e759f79c66167a743af859afbeefa324abe/system.slice/sshd.s>
└─88 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256>
Aug 22 03:45:02 prod_server systemd[1]: Starting OpenSSH server daemon...
Aug 22 03:45:02 prod_server sshd[88]: Server listening on 0.0.0.0 port 22.
Aug 22 03:45:02 prod_server sshd[88]: Server listening on :: port 22.
Aug 22 03:45:02 prod_server systemd[1]: Started OpenSSH server daemonEvet şuan çalışıyor.
jenkins sunucusundan ssh ile prod server’a bağlanmayı deneyelim. Password sorulduğu yerde kutsal password Ankara06 giriyoruz.
docker exec -it jenkins bash jenkins@515eab58379e:/$ ssh prod_user@prod_server The authenticity of host 'prod_server (172.18.0.3)' can't be established. ED25519 key fingerprint is SHA256:InXqKoqOxd61f5JUnKEk8R64aqBm3/MwnZU9VwY0eco. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'prod_server' (ED25519) to the list of known hosts. prod_user@prod_server's password: Ankara06 [prod_user@prod_server ~]$
[prod_user@prod_server ~]$ ifadesi bizim ssh ile jenkins’ten prod_server’a bağlandığımız anlamına geliyor.
Hayırlı uğurlu olsun.
Kullanılan tüm kodlar burada. Kendinizi bu konularda geliştirmek ve teknik olarak güçlendirmek için VBO Data Engineering Bootcamp‘e katılabilirsiniz.
Bir sonraki yazıya kadar hoşçakalın.
Kaynaklar
Kapak Görseli: Photo by Nikolett Emmert on Unsplash