Linux Container SSH Bağlantısı
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_server
imajını oluşturmak için kullanılacak Dockerfile’ın bulunduğu dizini belirtir. Bu durumda, Dockerfile,prod
adlı 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:
/run
ve/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/.ssh
dizinini, konteyner içindeki/home/prod_user/.ssh
dizinine 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-jdk17
imajı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ı
root
kullanı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
:ping
komutunu 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
pip
paket 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-packages
seç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 rsync
rsync
komutunu 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
jenkins
kullanıcısına geçirir. Bu, Jenkins işlemlerininjenkins
kullanı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"] EOF
FROM 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
:container
adında bir ortam değişkeni oluşturur ve değerinidocker
olarak 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
:sudo
komutunu 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çinpasswd
komutunu 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
:prod_user
adı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ı
wheel
grubuna ekler, böylecesudo
kullanarak yönetici ayrıcalıklarıyla komutlar çalıştırabilir. /home/prod_user/.ssh
dizinini oluşturur ve sahipliğiniprod_user
kullanıcısına verir./home/prod_user/
dizininin sahipliğini ve izinlerini ayarlar, böylece sadeceprod_user
erişebilir./home/prod_user/.ssh
dizininin izinlerini ayarlar, böylece sadece sahibi okuma, yazma ve yürütme yapabilir.
RUN echo "%wheel ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
:wheel
grubundaki kullanıcıların parola sorulmadansudo
kullanarak 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 yes
satı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.sh
adlı 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/cgroup
dizinini 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 files
Windows 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 daemon
Evet ş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