common commands between docker images

Viewed 150

I've 4 images which they do not share the same basic image :

image1 : FROM openjdk:8  
image2 : FROM mongo:3.6  
image3 : FROM ssh  
image4 : FROM ubuntu  

But at some point I've to execute the same commands on all of them, ex:

RUN useradd -s /bin/bash -p $(openssl passwd -1 user) -d /home/user -m -G sudo user
USER user
WORKDIR /home/user

RUN mkdir -p /home/user/.ssh/ && \
    chmod 0700 /home/user/.ssh  && \
    touch /home/user/.ssh/authorized_keys && \
    chmod 600 /home/user/.ssh/authorized_keys && \
    touch /home/user/.ssh/config && \
    chmod 600 /home/user/.ssh/config

COPY ssh-keys/ /keys/
RUN cat /keys/id_rsa.pub >> /home/user/.ssh/authorized_keys
RUN cat /keys/config >> /home/user/.ssh/config

and having the same directories structure :

image1  
--->ssh-keys  
------>config  
------>id_rsa  
------>id_rsa.pub  
--->Dockerfile

image2  
--->ssh-keys  
------>config  
------>id_rsa  
------>id_rsa.pub  
--->Dockerfile

image3  
--->ssh-keys  
------>config  
------>id_rsa  
------>id_rsa.pub  
--->Dockerfile

image4  
--->ssh-keys  
------>config  
------>id_rsa  
------>id_rsa.pub  
--->Dockerfile

Is there a way to remove this duplications ?

2 Answers

You might want to look into using a multi-stage build to serve as the base for all of your images and extend from there as needed; perhaps your base could be something like:

FROM scratch

# I like to keep all my image files under a single directory
COPY rootfs/ /

Then, in your other Dockerfiles:

FROM your-base-image AS base
FROM openjdk:8

COPY --from=base / /

[...]

Downside is there are only certain actions that will work as you expect in a multi-stage build, but copying files is one that should.

Scratch does not contain anything, better to use alpine as a base image and remove the below command from reusable section

RUN useradd -s /bin/bash -p $(openssl passwd -1 user) -d /home/user -m -G sudo user
USER user

As these commands vary from OS to OS(base image) and it will not work in alpine etc

So I will suggest something like

image1  
--->Dockerfile
image2  
--->Dockerfile
baseimage
--->ssh-keys  
------>config  
------>id_rsa  
------>id_rsa.pub  
--->Dockerfile

Desing base image

FROM alpine as sshconfig
WORKDIR /home/user

RUN mkdir -p /home/user/.ssh/ && \
    chmod 0700 /home/user/.ssh  && \
    touch /home/user/.ssh/authorized_keys && \
    chmod 600 /home/user/.ssh/authorized_keys && \
    touch /home/user/.ssh/config && \
    chmod 600 /home/user/.ssh/config
COPY ssh-keys/ /keys/
RUN cat /keys/id_rsa.pub >> /home/user/.ssh/authorized_keys
RUN cat /keys/config >> /home/user/.ssh/config

Build this image

docker build -t sshconfig .

Now subsequent Docker Image will copy from this sshconfig Docker base image.

Image1

FROM ubuntu
# Add user
# change user

# copy ssh-config from base image
COPY --from=sshconfig /home/user/.ssh /home/user/.ssh

#for testing and verify keys
COPY --from=sshconfig /keys/ /keys/
# list keys copies form base image
RUN ls -lstrah /home/user/ /home/user/.ssh /keys/
Related