I use Jenkins as a docker container in a custom Docker image, starting it like:
docker run -dt --privileged -p 8080:8080 -p 80:80 -p 443:443 -p 40440:40440 \
--name jenkins-master-$(hostname) \
--restart unless-stopped \
-h jenkins-master-$(hostname) \
-v $LOCAL_JENKINS_ROOT_DIR/ssl:/etc/nginx/ssl \
-v $LOCAL_JENKINS_ROOT_DIR/users:/var/jenkins/users \
-v $LOCAL_JENKINS_ROOT_DIR/jobs:/var/jenkins/jobs \
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-v /var/log/jenkins:/var/log/jenkins \
[artifactory-url-here]/jenkins-master:prod
Lately, I've noticed that my container randomly restarts throughout the day, and using docker events I discovered that everytime it was restarted automatically, there was a quadruple like this:
2020-02-28T12:55:08.022251372+01:00 container die 87c7c5601bdee803072d2c8fe9405cb56b765ba6b1298461fbe17304979d7c2a (exitCode=0, image=ulcentral.ullink.lan:5001/ul-jenkins-master:prod, name=jenkins-master-cos-jenkins-prd-qEvu, version=1.0+beta.2)
2020-02-28T12:55:08.278391656+01:00 network disconnect c5afeafee778f463af73e5b7cc305cb90f0a6d6c0d81e8814cd43e5d73bac24e (container=87c7c5601bdee803072d2c8fe9405cb56b765ba6b1298461fbe17304979d7c2a, name=bridge, type=bridge)
2020-02-28T12:55:08.426582932+01:00 network connect c5afeafee778f463af73e5b7cc305cb90f0a6d6c0d81e8814cd43e5d73bac24e (container=87c7c5601bdee803072d2c8fe9405cb56b765ba6b1298461fbe17304979d7c2a, name=bridge, type=bridge)
2020-02-28T12:55:08.993064785+01:00 container start 87c7c5601bdee803072d2c8fe9405cb56b765ba6b1298461fbe17304979d7c2a (image=ulcentral.ullink.lan:5001/ul-jenkins-master:prod, name=jenkins-master-cos-jenkins-prd-qEvu, version=1.0+beta.2)
The exitcode is 0, I need more info on how to debug the underlying reason that the container stops.
Docker image (some sections omitted due to privacy reasons):
FROM debian:stretch
LABEL version 1.0+beta.2
ENV JENKINS_HOME /var/jenkins
ENV DEBIAN_FRONTEND noninteractive
RUN echo "moonlight:/share/dev-common/Applications/x86-64/linux /mnt/applis nfs defaults 0 0" >> /etc/fstab && \
echo "moonlight:/share/home /home nfs defaults 0 0" >> /etc/fstab && \
echo "sharing:/mnt/samba/share /mnt/share nfs defaults 0 0" >> /etc/fstab
# Global config
# FIXME: nfs mounting hangs forever, so no path, etc...
RUN echo "nslcd nslcd/ldap-base string dc=openldap,dc=ullink,dc=lan" | debconf-set-selections && \
echo "nslcd nslcd/ldap-uris string ldap://ldap" | debconf-set-selections && \
echo "libnss-ldapd:amd64 libnss-ldapd/nsswitch multiselect group, passwd, shadow" | debconf-set-selections
RUN apt-get upgrade -y && apt-get update
RUN apt-get -y install \
git \
libnss-ldapd \
libpam-ldapd \
locales \
maven \
nfs-common \
ntp \
openjdk-8-jdk \
openssh-server \
python2.7 \
sudo \
supervisor \
unzip \
vim \
wget \
ca-certificates \
nginx \
--no-install-recommends
RUN wget https://bootstrap.pypa.io/get-pip.py && \
python get-pip.py && \
rm get-pip.py && \
pip install pywinrm
RUN sed 's/#PermitRootLogin yes/PermitRootLogin yes/' -i /etc/ssh/sshd_config && \
sed 's/# fr_FR.UTF-8/fr_FR.UTF-8/' -i /etc/locale.gen && \
sed 's/# en_US.UTF-8/en_US.UTF-8/' -i /etc/locale.gen && \
locale-gen && \
update-locale LANG=en_US.UTF-8 && \
echo 'Europe/Paris' > /etc/timezone && \
cp /usr/share/zoneinfo/Europe/Paris /etc/localtime
RUN mkdir -p /var/run/sshd \
/var/log/supervisor \
/var/log/jenkins \
/mnt/applis \
/mnt/share \
$JENKINS_HOME/plugins
# until https://github.com/jenkinsci/jenkins/pull/3293 is merged we use a custom Jenkins build
# For some reason wget doesn't recognize the GoDaddy certs, even with `ca-certificates` being installed
RUN wget --no-proxy --no-check-certificate https://ulcentral.itiviti.com/artifactory/ext-release-local/org/jenkins-ci/main/jenkins-war/2.187-ullink/jenkins-war-2.187-ullink.war \
-O $JENKINS_HOME/jenkins.war
COPY packaged/install_plugin.sh $JENKINS_HOME/install_plugin.sh
RUN JENKINS_HOME=$JENKINS_HOME \
$JENKINS_HOME/install_plugin.sh \
[A LIST OF JENKINS PLUGINS]
COPY packaged/bootstrap.sh /var/bootstrap.sh
COPY packaged/subversion_servers /root/.subversion/servers
ADD packaged/ssh $JENKINS_HOME/ssh
COPY packaged/proxy.xml $JENKINS_HOME/proxy.xml
COPY packaged/commit-jenkins-config.sh /usr/bin/commit-jenkins-config.sh
COPY packaged/ntp.conf /etc/ntp.conf
COPY packaged/default.conf /etc/nginx/sites-available/default
RUN chmod +x /var/bootstrap.sh
RUN chmod +x /usr/bin/commit-jenkins-config.sh
EXPOSE 8080
EXPOSE 443
# For jnlp agents
EXPOSE 40440
WORKDIR $JENKINS_HOME
CMD ["/var/bootstrap.sh"]
# OUTPUT OF DOCKER INFO:
Containers: 1
Running: 1
Paused: 0
Stopped: 0
Images: 57
Server Version: 18.09.6
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: bb71b10fd8f58240ca47fbb579b9d1028eea7c84
runc version: 2b18fe1d885ee5083ef9f0838fee39b62d653e30
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-693.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.639GiB
Name: cos-jenkins-prd
ID: NTNU:KI65:HCY3:5EG4:AGN5:NUGB:HS7U:I75I:LSVE:EEBN:ZY7D:HU3M
Docker Root Dir: /opt/docker/lib
Debug Mode (client): false
Debug Mode (server): false
HTTP Proxy: http://proxy.ullink.lan:9876/
HTTPS Proxy: http://proxy.ullink.lan:9876/
No Proxy: ulcentral,.ullink.lan,localhost,127.0.0.1
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
localhost:5001
ulcentral.ullink.lan:5001
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
EDIT
Contents of the bootstrap.sh file (used to start the jenkins process):
#!/bin/bash
export http_proxy https_proxy no_proxy
systemctl start commit-jenkins-config.timer
nslcd
rpcbind
service ntp start
service nginx start
$(which sshd)
cd $JENKINS_HOME && git pull
java -XX:+ExitOnOutOfMemoryError -Dhttp.proxyHost=proxy.ullink.lan -Dhttp.proxyPort=9876 -Dhttps.proxyHost=proxy.ullink.lan -Dhttps.proxyPort=9876 -Dhttp.nonProxyHosts="LIST OF HOSTS HERE" -Dhudson.remoting.ExportTable.unexportLogSize=0 -Dhudson.model.ParametersAction.keepUndefinedParameters=false -Dhudson.model.DirectoryBrowserSupport.CSP="" -jar jenkins.war -httpPort=8080 --sessionTimeout=10080 --httpKeepAliveTimeout=60000 2>&1 | tee /var/log/jenkins/jenkins.log
docker logs {containername} - it shows what was going on inside of the container.
or
kubectl logs {containername} - shows you logs, if you are using kuberneties.
for me it shows logs even if container was stopped(restarted) which is very useful to se the reason why.
And you need to make sure that you output as much as you can inside of container - if you are running some application inside do console output for any error you have.
But in general i bet that that is happening for you because of memory lack - you can just try increase amount of memory available for container. (depends on the way you are running container, would definitely recommend kubernetes for production - way more control on everything).
Related
I have a pretty simple docker-compose setup working fine in Ubuntu 20 Desktop, but not working the same in Ubuntu 20 WSL2 in Windows 10:
version: "3.8"
services:
webserver_awesome:
container_name: myawesomesite.xyz
hostname: myawesomesite.xyz
build: ./webserver
volumes:
- './app/:/var/www/html'
depends_on:
- db_awesome
networks:
- internal_myawesomesite
db_awesome:
image: mysql:5.7
ports:
- '3310:3306'
environment:
MYSQL_ROOT_PASSWORD: 'secret'
MYSQL_DATABASE: 'myawesomesite'
MYSQL_USER: 'myawesomesite'
MYSQL_PASSWORD: 'secret'
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
networks:
- internal_myawesomesite
volumes:
- './mysql:/var/lib/mysql'
redis_awesome:
image: 'redis:alpine'
ports:
- '6381:6379'
volumes:
- './redis/:/data'
networks:
- internal_myawesomesite
networks:
internal_myawesomesite:
driver: bridge
My ./webserver Dockerfile is an ubuntu with an nginx, php7.4, xdebug, and looks like so:
FROM ubuntu:20.04
LABEL maintainer="Cristian E."
WORKDIR /var/www/html
ENV TZ=UTC
RUN apt-get update \
&& apt-get install -y iputils-ping \
&& apt-get install -y nginx \
&& apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python2 \
&& mkdir -p ~/.gnupg \
&& chmod 600 ~/.gnupg \
&& echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf \
&& apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E5267A6C \
&& apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C300EE8C \
&& echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu focal main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \
&& apt-get update \
&& apt-get install -y php7.4-cli php7.4-dev \
php7.4-pgsql php7.4-sqlite3 php7.4-gd \
php7.4-curl php7.4-memcached \
php7.4-imap php7.4-mysql php7.4-mbstring \
php7.4-xml php7.4-zip php7.4-bcmath php7.4-soap \
php7.4-intl php7.4-readline \
php7.4-msgpack php7.4-igbinary php7.4-ldap \
php7.4-redis \
php7.4-fpm \
nano \
&& pecl install xdebug-3.0.0 \
&& php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \
&& curl -sL https://deb.nodesource.com/setup_15.x | bash - \
&& apt-get install -y nodejs \
&& apt-get -y autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# DELETE DEFAULT NGINX SITE & REPLACE WITH OUR ONE
RUN rm -rf /etc/nginx/sites-available/default
RUN npm install -g laravel-echo-server
# Turn off daemon mode, so we can control nginx via supervisor
# supervisord can only handle processes in foreground. The default for nginx is running in background as daemon. To ensure that your nginx is running with supervisord you have to set 'daemon off' in your nginx.conf
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
RUN mkdir /etc/nginx/ssl
COPY ./ssl /etc/nginx/ssl
COPY ./php7.4/nginx/default.conf /etc/nginx/sites-available/default
COPY ./run.sh ./
COPY ./php7.4/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY ./php7.4/php.ini /etc/php/7.4/fpm/conf.d/custom-php.ini
RUN sed -i 's/user = www-data/user = 1000/g' /etc/php/7.4/fpm/pool.d/www.conf
RUN sed -i 's/group = www-data/group = 1000/g' /etc/php/7.4/fpm/pool.d/www.conf
#RUN chmod -R 775 /var/www/html/storage
# Make permissions play nice
RUN usermod -u 1000 www-data
RUN chown -R 1000:1000 /var/www
What works in Ubuntu 20 Desktop:
I run docker-compose up, the webserver_awesome container goes up and it gets an IP address automatically (as it should);
if I inspect that container and put that container's ip address inside /etc/hosts like so:
xxx.xxx.xx.xx myawesomesite.xyz
then I can access myawesomesite.xyz in the browser and it works fine. I can access it via port 80 or 443 or any port that may be configured inside my nginx sites configs (see Dockerfile)
If you look at docker-compose you will see that I am not publishing any ports for webserver_awesome container and yet it is accessible from the host OS via the container's ip
The reason why I like this is because I can have many of these docker-compose instances, one for each php project that I'm working on, and I can then map the ips of those webserver containers inside /etc/hosts to top level domains like myawesomesite.xyz, anothersite.xyz, yetanother.xyz and I can access all sites at the same time on port 80 or 443 without conflicts.
Side note:
What usually is shown as general practice with local docker dev enviroments is that they publish port 8080 to the host and access the app via localhost:8080, and that is just not very good if you want to work on multiple projects at the same time and use port 443 for each one, and also many third party apis don't accept localhost as a domain or any other port except 443.
What doesn't work in Ubuntu 20 WSL2:
If I run docker-compose up just like on Ubuntu 20 Desktop, I can't ping the container's ip from inside Ubuntu 20 WSL (even though the docker-compose up command was ran from inside Ubuntu 20 WSL too.
Also, if I put the ip in the /etc/hosts file of Ubuntu 20 WSL, I can't access the site. It just hangs forever.
So my question is, why is networking working in one way on native Ubuntu 20 Desktop and why is it working differently on Ubuntu 20 over WSL (even though the tests I did were done from the command line from inside Ubuntu in both cases)
I am running an Elastic and Kibana service within a container using an Azure Web app container service. I was keen on checking the SSH connectivity for this container using Azures Web SSH console feature. Followed the microsoft documentation for SSH into custom containers https://learn.microsoft.com/en-us/azure/app-service/configure-custom-container?pivots=container-linux#enable-ssh which shows the example of running the container as default root user.
My issue is Elasticsearch process does not run as a root user so I had to make the sshd process run as an elastic user. I was able to get the sshd process running which accepts the SSH connection from my host however the credentials I am setting in the docker file (elasticsearch:Docker!) are throwing Access Denied error.Any idea where i am going wrong here?
Dockerfile
FROM openjdk:jre-alpine
ARG ek_version=6.5.4
RUN apk add --quiet --no-progress --no-cache nodejs wget \
&& adduser -D elasticsearch \
&& apk add openssh \
&& echo "elasticsearch:Docker!" | chpasswd
# Copy the sshd_config file to the /etc/ssh/ directory
COPY startup.sh /home/elasticsearch/
RUN chmod +x /home/elasticsearch/startup.sh && \
chown elasticsearch /home/elasticsearch/startup.sh
COPY sshd_config /home/elasticsearch/
USER elasticsearch
WORKDIR /home/elasticsearch
ENV ES_TMPDIR=/home/elasticsearch/elasticsearch.tmp ES_DATADIR=/home/elasticsearch/elasticsearch/data
RUN wget -q -O - https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-${ek_version}.tar.gz \
| tar -zx \
&& mv elasticsearch-${ek_version} elasticsearch \
&& mkdir -p ${ES_TMPDIR} ${ES_DATADIR} \
&& wget -q -O - https://artifacts.elastic.co/downloads/kibana/kibana-oss-${ek_version}-linux-x86_64.tar.gz \
| tar -zx \
&& mv kibana-${ek_version}-linux-x86_64 kibana \
&& rm -f kibana/node/bin/node kibana/node/bin/npm \
&& ln -s $(which node) kibana/node/bin/node \
&& ln -s $(which npm) kibana/node/bin/npm
EXPOSE 9200 5601 2222
ENTRYPOINT ["/home/elasticsearch/startup.sh"]
startup.sh script
#!/bin/sh
# Generating hostkey
ssh-keygen -f /home/elasticsearch/ssh_host_rsa_key -N '' -t rsa
# starting sshd process
echo "Starting SSHD"
/usr/sbin/sshd -f sshd_config
# Staring the ES stack
echo "Starting ES"
sh elasticsearch/bin/elasticsearch -E http.host=0.0.0.0 & kibana/bin/kibana --host 0.0.0.0
sshd_config file
Port 2222
HostKey /home/elasticsearch/ssh_host_rsa_key
PidFile /home/elasticsearch/sshd.pid
ListenAddress 0.0.0.0
LoginGraceTime 180
X11Forwarding yes
Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr
MACs hmac-sha1,hmac-sha1-96
StrictModes yes
SyslogFacility DAEMON
PasswordAuthentication yes
PermitEmptyPasswords no
PermitRootLogin yes
Subsystem sftp internal-sftp
Error i am getting
Please check and verify that your docker image supports SSH. It would appear that you have done everything correctly so one of the final troubleshooting steps left as this point is to verify that your image supports SSH to begin with.
I was trying to use the hostnetworking mode, which is supposed to share the same networking namespace as the Docker host, according to https://docs.docker.com/network/host/.
However, when I use nc to listen in on a port within the image, I'm unable to see that port listening on the host.
Dockerfile:
FROM kalilinux/kali-rolling
LABEL version="1.0" \
author="[Redacted Author]" \
description="Kali Docker Image"
RUN echo "deb http://http.kali.org/kali kali-rolling main contrib non-free" > /etc/apt/sources.list && \
echo "deb-src http://http.kali.org/kali kali-rolling main contrib non-free" >> /etc/apt/sources.list && \
echo "kali-docker" > /etc/hostname && \
set -x && \
apt-get -yqq update && \
apt-get -yqq dist-upgrade && \
apt-get clean && \
apt-get install -yqq vim telnet nmap metasploit-framework sqlmap wpscan netcat
WORKDIR /root
docker-compose.yml:
version: "3.4"
services:
kali:
build:
network: host
context: .
dockerfile: Dockerfile
volumes:
- ./kali-root:/root
tty: true
privileged: true
I built and ran the image in the following manner:
docker-compose build
docker-compose up -d
When I run nc -lvnp 80 from within the image, I'm unable to see anything on the host. Example:
root#kali:~/kali# docker-compose exec kali bash
root#29613f1a15fe:~# nc -lvnp 80
Listening on 0.0.0.0 80
and on the host:
root#kali:~# netstat -antp | grep -i listen
root#kali:~#
What am I doing wrong or missing here?
I've 4 containers configured like the following (docker-compose.yml):
version: '3'
networks:
my-ntwk:
ipam:
config:
- subnet: 172.20.0.0/24
services:
f-app:
image: f-app
tty: true
container_name: f-app
hostname: f-app.info.my
ports:
- "22:22"
networks:
my-ntwk:
ipv4_address: 172.20.0.5
extra_hosts:
- "f-db.info.my:172.20.0.6"
- "p-app.info.my:172.20.0.7"
- "p-db.info.my:172.20.0.8"
depends_on:
- f-db
- p-app
- p-db
f-db:
image: f-db
tty: true
container_name: f-db
hostname: f-db.info.my
networks:
my-ntwk:
ipv4_address: 172.20.0.6
p-app:
image: p-app
tty: true
container_name: p-app
hostname: p-app.info.my
networks:
my-ntwk:
ipv4_address: 172.20.0.7
p-db:
image: p-db
tty: true
container_name: prod-db
hostname: p-db.info.my
networks:
my-ntwk:
ipv4_address: 172.20.0.8
Each image is build by the same Dockerfile :
FROM openjdk:8
RUN apt-get update && \
apt-get install -y openssh-server
EXPOSE 22
RUN useradd -s /bin/bash -p $(openssl passwd -1 myuser) -d /home/nf2/ -m myuser
ENTRYPOINT service ssh start && bash
Now I want to be able to connect from f-app to any other machine without typing the password when running this line : ssh myuser#f-db.info.my.
I know that I need to exchange ssh-keys between the servers (thats not a problem). My problem is how to do it with docker containers and when (build or runtime)!
For doing ssh without password you to need to create passwordless user along with configuring SSH keys in the container, plus you will also need to add ssh keys in the sources container plus public key should be added in the authorized of the destination container.
Here is the working Dockerfile
FROM openjdk:7
RUN apt-get update && \
apt-get install -y openssh-server vim
EXPOSE 22
RUN useradd -rm -d /home/nf2/ -s /bin/bash -g root -G sudo -u 1001 ubuntu
USER ubuntu
WORKDIR /home/ubuntu
RUN mkdir -p /home/nf2/.ssh/ && \
chmod 0700 /home/nf2/.ssh && \
touch /home/nf2/.ssh/authorized_keys && \
chmod 600 /home/nf2/.ssh/authorized_keys
COPY ssh-keys/ /keys/
RUN cat /keys/ssh_test.pub >> /home/nf2/.ssh/authorized_keys
USER root
ENTRYPOINT service ssh start && bash
docker-compose will remain same, here is the testing script that you can try.
#!/bin/bash
set -e
echo "start docker-compose"
docker-compose up -d
echo "list of containers"
docker-compose ps
echo "starting ssh test from f-db to f-app"
docker exec -it f-db sh -c "ssh -i /keys/ssh_test ubuntu#f-app"
For further detail, you can try the above working example docker-container-ssh
git clone git#github.com:Adiii717/docker-container-ssh.git
cd docker-container-ssh;
./test.sh
You can replace the keys as these were used for testing purpose only.
If you are using docker compose an easy choice is to forward SSH agent like that:
something:
container_name: something
volumes:
- $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
environment:
SSH_AUTH_SOCK: /ssh-agent
ssh-forwarding on macOS hosts - instead of mounting the path of $SSH_AUTH_SOCK, you have to mount this path - /run/host-services/ssh-auth.sock
or you can do it like:
It's a harder problem if you need to use SSH at build time. For example if you're using git clone, or in my case pip and npm to download from a private repository.
The solution I found is to add your keys using the --build-arg flag. Then you can use the new experimental --squash command (added 1.13) to merge the layers so that the keys are no longer available after removal. Here's my solution:
Build command
$ docker build -t example --build-arg ssh_prv_key="$(cat ~/.ssh/id_rsa)" --build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" --squash .
Dockerfile
FROM openjdk:8
ARG ssh_prv_key
ARG ssh_pub_key
RUN apt-get update && \
apt-get install -y \
git \
openssh-server \
libmysqlclient-dev
# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
chmod 0700 /root/.ssh && \
ssh-keyscan github.com > /root/.ssh/known_hosts
# Add the keys and set permissions
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
echo "$ssh_pub_key" > /root/.ssh/id_rsa.pub && \
chmod 600 /root/.ssh/id_rsa && \
chmod 600 /root/.ssh/id_rsa.pub
RUN apt-get update && \
apt-get install -y openssh-server && \
apt-get install -y openssh-client
EXPOSE 22
RUN useradd -s /bin/bash -p $(openssl passwd -1 myuser) -d /home/nf2/ -m myuser
ENTRYPOINT service ssh start && bash
If you're using Docker 1.13+ and/or have experimental features on you can append --squash to the build command which will merge the layers, removing the SSH keys and hiding them from docker history.
I have a docker-compose YAML file set up to build an Ansible container on the alpine:3.7 image, and 3 other Docker containers that will be managed by the Ansible container. I have been able to configure the inventory for the Ansible server in a way to use ansible_connection=docker for the other containers, but am not able to connect to the underlying Docker host machine from the Ansible container. (MacOS)
The problem is that we need to be able to communicate with the host for file transfers that the Ansible container would request as part of playbooks being executed there, but I'm not sure how to set up the host and/or container to achieve the proper connection. This is for a development environment, so it doesn't need to be ultra-secure, though I generally prefer best practices, even if the environment wouldn't necessarily call for it.
I've tried using a local connection type, but realized that Ansible resolves that as the machine that it is running on, which is the container. I've also attempted to look up how to create and share an SSH key between the host and container, but am not understanding the concept behind it and am not sure if the articles I've come across promote the best practice for sharing the keys and establishing communications. I was avoiding using host.docker.internal to resolve the host IP in the container as it is only recognized in Mac and Windows, and not in production mode (from what I've found online).
docker-compose.yml
version: '3'
services:
ansible:
container_name: ansible
build:
context: ./ansible/
volumes:
- ${DOCKERBUILD}/ansible:/ansible
- /var/run/docker.sock:/var/run/docker.sock
networks:
- project-network
extra_hosts:
# Tried setting the gateway address for the subnet in the custom network as a host
# on the Ansible container, but still cannot connect: Connection refused on port 22.
- dockerhost:172.55.0.1
oracle11g:
container_name: oracle11g
build:
context: ./oracle11g/
environment:
- ORACLE_PWD=oracle
ports:
- 1521:1521
volumes:
- ${DOCKERSHARE}/oracle11g/tmp:/tmp
networks:
- project-network
# OTHER CONTAINERS OMITTED FOR BREVITY.
networks:
project-network:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.55.0.0/16
Dockerfile (ansible container)
FROM alpine:3.7
ENV ANSIBLE_VERSION 2.7.0
ARG ANSIBLE_SETUP_DIR=./setup
ARG ANSIBLE_ETC=/etc/ansible
# Install missing dependencies
# --------------------------------------------------------------------
ENV BUILD_PACKAGES \
bash \
curl \
tar \
openssh-client \
sshpass \
git \
python \
py-boto \
py-dateutil \
py-httplib2 \
py-jinja2 \
py-paramiko \
py-pip \
py-yaml \
ca-certificates \
docker
# Copy host file
# --------------------------------------------------------------------
RUN mkdir -p /etc/ansible/
COPY $ANSIBLE_SETUP_DIR/hosts $ANSIBLE_SETUP_DIR/ssh.config $ANSIBLE_ETC/
# Install Ansible
# --------------------------------------------------------------------
RUN set -x && \
\
echo "==> Adding build-dependencies..." && \
apk --update add --virtual build-dependencies \
gcc \
musl-dev \
libffi-dev \
openssl-dev \
python-dev && \
\
echo "==> Upgrading apk and system..." && \
apk update && apk upgrade && \
\
echo "==> Adding Python runtime..." && \
apk add --no-cache ${BUILD_PACKAGES} && \
pip install --upgrade pip && \
pip install python-keyczar && \
\
echo "==> Installing Ansible..." && \
pip install ansible==${ANSIBLE_VERSION} && \
\
echo "==> Cleaning up..." && \
apk del build-dependencies && \
rm -rf /var/cache/apk/* && \
echo "==> Appending SSH config for host..." && \
cat $ANSIBLE_ETC/ssh.config >> /root/.ssh/ssh_config && \
rm -rf $ANSIBLE_ETC/ssh.config
ENV ANSIBLE_GATHERING smart
ENV ANSIBLE_HOST_KEY_CHECKING false
ENV ANSIBLE_RETRY_FILES_ENABLED false
ENV ANSIBLE_ROLES_PATH /ansible/playbooks/roles
ENV ANSIBLE_SSH_PIPELINING True
ENV PYTHONPATH /ansible/lib
ENV PATH /ansible/bin:$PATH
ENV ANSIBLE_LIBRARY /ansible/library
ENV ANSIBLE_HOME=/ansible/
# In milliseconds, represents 9800+ years.
ENV INFINITY=2147483647d
WORKDIR ${ANSIBLE_HOME}
EXPOSE 22
# Keep container alive by issuing default entrypoint of "infinite" sleep.
ENTRYPOINT ["sleep", "2147483647d"]
inventory ($ANSIBLE_SETUP_DIR/hosts)
[host]
dockerhost
[docker-containers]
ansible ansible_connection=local
oracle11g ansible_connection=docker
I've seen a few articles on stackoverflow regarding communications from the host to the container, but relatively few for the reverse, and none that seemed to resolve this specific problem (to me, anyway). Hope someone has the answer. Thanks!
...and 3 other Docker containers that will be managed by the Ansible
container.
Docker containers are not meant to be managed in this way, running container images should be expected to be immutable, which is to say they are not expected to change once deployed.
Everything you need inside your running docker image should be managed by the container image build process, the environment variables, the mounted volumes, and the application running inside.
If you need to change something in a running container, a new image should be built and deployed.
I don't know if this will help you, i created an ansible-docker image to manage my home network, including the machine it is running on.
i use docker run for this, as i only want to run the container if i need to do something, afterwards it can be removed.
I came across this thread as i was having a similar issue, and i solved it by doing docker rum --rm -it --network host
So the solution should be, to add --network host in your docker-compose file.
hth