---
# System prepended metadata

title: 使用Dockerfile 來建立互相操作的Container（附Crontab)
tags: [DevOps, Docker, Code, Container, Notes]

---

# 使用Dockerfile 來建立互相操作的Container（附Crontab)
> 2019 10/05 黑田
> 
目前container是無法互相下指令的。所以用這個方法可以讓container互相進行操作。
目前這是權宜的做法，希望未來docker 可以有類似的功能。

[TOC]

情境
---
我正在使用docker-compose 建置一個laravel的環境。
環境建置完成，laralvel也可以跑。現在問題來了，我想要使用crontab 來對php 定期下php artisan 的指令，但是php container的版本是使用alpine，這個版本是沒有crontab功能的。
所以我做了這些事情：

- 用dockerfile安裝crontab
- 用CMD把crontab服務跑起來

後來我就放棄了，因為crontab一直跑不起來。
所以我改用了這個做法：
crontab 的Dockerfile資料夾內的內容：

Dockerfile
```dockerfile
FROM alpine:3.10

COPY script.sh /script.sh
COPY crontab /crontab
COPY entry.sh /entry.sh
RUN chmod 755 /script.sh /entry.sh
RUN /usr/bin/crontab /crontab

RUN apk add --update --no-cache openssh sshpass
 
ENTRYPOINT ["/entry.sh"]
```

entry.sh
```bash

#!/bin/sh

# start cron
sshpass -p root ssh -o StrictHostKeyChecking=no root@targetContainer echo 'ssh successed'
/usr/sbin/crond -f -l 8
```

script.sh
```bash
#!/bin/bash
# 你打算定期執行的內容
```
crontab
```shell
*	*	*	*   *  sh /backup/mysql-backup.sh
```

以上就是crontab 這個container在build的過程。 

而重點是被操作的container 的dockerfile 必須要有安裝ssl的部分：

> 這裡以php alpine為例， 如果不是alpine請參考其他做法
```dockerfile
#ssh
FROM php:7.3.10-fpm-alpine
#其他需要安裝的套件
RUN apk add --update
RUN apk add composer libpng-dev libintl  gettext-dev libxml2-dev libzip-dev
RUN docker-php-ext-install mbstring xml gettext gd mysqli zip 
RUN docker-php-ext-configure pdo_mysql && docker-php-ext-install pdo_mysql


#SSH的部分
RUN apk --update add --no-cache openssh bash \
  && sed -i s/#PermitRootLogin.*/PermitRootLogin\ yes/ /etc/ssh/sshd_config \
  && echo "root:root" | chpasswd \
  && rm -rf /var/cache/apk/*
RUN sed -ie 's/#Port 22/Port 22/g' /etc/ssh/sshd_config
RUN sed -ri 's/#HostKey \/etc\/ssh\/ssh_host_key/HostKey \/etc\/ssh\/ssh_host_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_rsa_key/HostKey \/etc\/ssh\/ssh_host_rsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_dsa_key/HostKey \/etc\/ssh\/ssh_host_dsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_ecdsa_key/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_ed25519_key/HostKey \/etc\/ssh\/ssh_host_ed25519_key/g' /etc/ssh/sshd_config
RUN /usr/bin/ssh-keygen -A
RUN ssh-keygen -t rsa -b 4096 -f  /etc/ssh/ssh_host_key

CMD ["/usr/sbin/sshd","-D"]
```


要注意的是，如果需要複數的CMD ，最好把這些指令寫成script ，然後用CMD一次執行這個script，不然之前的dockerfile 甚至前面寫的CMD都會被蓋掉。

並且，這兩個container 必須要有network互相連接，這樣才有辦法互相連接，以我的狀況是
進入crontab的container 後，可以ping到 php的container。


如果要在crontab這個container中對php下指令，只需要模仿crontab中的指令就好了。
```bash
sshpass -p root ssh -o StrictHostKeyChecking=no root@targetContainer echo 'ssh successed'
```
這行指令的意思是
以root的身份 密碼為root 要讓targetContainer 回傳一個`ssh successed`的字樣。


###### tags: `Notes` `Docker` `Code` `Container` `DevOps`
