package manager for docker container running image busybox:uclibc - docker

I want to install net-tools on one of my running containers, which is running busybox:uclibc image. But this image doesn't have any package manager like apt-get or apk. Is there a way to do it or should I just make changes to my image?

Anything based on Busybox doesn't have a package manager. It's a single binary with a bunch of symlinks into it, and the way to add software to it is to write C code and recompile. That is, /bin/busybox literally is ls and sed and sh and cp and ...

Related

Mount-ing a CDROM repo during docker build

I'm building a docker image which also involves a small yum install. I'm currently in a location where firewall's and access controls makes docker pull, yum install etc extremely slow.
In my case, its a JRE8 docker image using this official image script
My problem:
Building the image requires just 2 libraries (gzip + tar) which combined is only of (132 kB + 865 kB). But the yum inside docker build script will first download the repo information which is over 80 MB. While 80 MB is generally small, here, this took over 1 hour just to download. If my colleagues need to build, this would be sheer waste of productive time, not to mention frustration.
Workarounds I'm aware of:
Since this image may not need the full yum power, I can simply grab the *.rpm files, COPY in container script and use rpm -i instead of yum
I can save the built image and locally distribute
I could also find closest mirror for docker-hub, but not yum
My bet:
I've copy of the linux CD with about the same version
I can add commands in dockerfile to rename the *.repo to *.repo.old
Add a cdrom.repo in /etc/yum.repos.d/ inside the container
Use yum to load most common libraries from the CDROM instead of internet
My problem:
I'm not able to make out how to create a mount point to a cdrom repo from inside the container build without using httpd.
In plain linux I do this:
mkdir /cdrom
mount /dev/cdrom /cdrom
cat > /etc/yum.repos.d/cdrom.repo <<EOF
[cdrom]
name=CDROM Repo
baseurl=file:///cdrom
enabled=1
gpgcheck=1
gpgkey=file:///cdrom/RPM-GPG-KEY-oracle
EOF
Any help appreciated.
Docker containers cannot access host devices. I think you will have to write a wrapper script around the docker build command to do the following
First mount the CD ROM to a directory within the docker context ( that would be a sub-directory where your DockerFile exists).
call docker build command using contents from this directory
Un-mount the CD ROM.
so,
cd docker_build_dir
mkdir cdrom
mount /dev/cdrom cdrom
docker build "$#" .
umount cdrom
In the DockerFile, you would simple do this:
RUN cd cdrom && rpm -ivh rpms_you_need

build a docker image that can use LLVM to compile ROS projects

I intend to build a Docker image that could use LLVM to compile ROS project code. According to Docker's official document https://docs.docker.com/config/containers/multi-service_container/ that it's better to avoid multiple services in one container. LLVM and ROS both got their Docker Image, how to compose these two into one and ship it together?
Update (2019.12.13):
If all you want to do use clang within the official ROS docker images, you can do something like this:
FROM ros:melodic
RUN apt-get -y install clang-6.0
RUN update-alternatives --install /usr/bin/c++ c++ $(command -v clang++-6.0) 1000
RUN update-alternatives --install /usr/bin/cc cc $(command -v clang-6.0) 1000
You can do this because the official ROS images inherit from Ubuntu images which use update-alternatives to manage how generic commands (e.g., C/C++ compilers) map to the packages that provide them. In brief, the calls to update-alternatives will install various symlinks such that /usr/bin/cc and /usr/bin/c++ both (eventually) point to clang-6.0 and clang++-6.0, respectively.
For detail on how update-alternatives works, refer to its man page.
Original answer follows.
You have a few strategies available to you:
Combine Dockerfiles
If you have access to both Dockerfiles, then try combining the content therein into one Dockerfile. You'll have to choose a single FROM instruction, but other instructions can be combined in the manner of your choosing.
Change the FROM on one
If you have access to only one Dockerfile, then try changing its FROM instruction to inherit from the other image. E.g., the ros:kinetic-ros-core-xenial image inherits from ubuntu:xenial; try changing it to inherit from, say, reaverproject/llvm.
ADD both tarballs
If you have access to neither Dockerfile, then you'll have to reverse-engineer a bit. Start by creating a "noop" container from each image and exporting a filesystem tarball therefrom. I.e., do...
$ docker container run --name noop-foobar foobar sh -c 'exit 0'
$ docker container export --output foobar.tar noop-foobar
$ docker container rm noop-foobar
...substituting "foobar" as necessary.
Once you have exported both filesystem tarballs, create a "base image" by ADDing them to a scratch image:
FROM scratch
ADD llvm.tar
ADD ros.tar
...
It's very likely you'll have to manually resolve conflicts between filesystem tarballs to get the base image working as intended.
References:
https://docs.docker.com/engine/reference/builder/
https://hub.docker.com/_/ros
https://docs.docker.com/engine/reference/commandline/container_export/
https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch

How to share apt-package across Docker containers

I want to use docker to help me stay organized with developing and deploying package/systems using ROS (Robot Operating System).
I want to have multiple containers/images for various pieces of software, and a single image that has all of the ROS dependencies. How can I have one container use the apt-packaged from my dependency master container?
For example, I may have the following containers:
MyRosBase: sudo apt-get install all of the ros dependencies I need (There are many). Set up some other Environment variables and various configuration items.
MyMoveApplication: Use the dependencies from MyRosBase and install any extra and specific dependencies to this image. Then run software that moves the robot arm.
MySimulateApplication: Use the dependencies from MyRosBase and install any extra and specific dependencies to this image. Then run software that simulates the robot arm.
How do I use apt packages from container in another container without reinstalling them on each container each time?
You can create your own images that serve you as base images using Dockerfiles.
Example:
mkdir ROSDocker
cd ROSDocker
vim Dockerfile-base
FROM debian:stretch-slim
RUN apt-get install dep1 dep2 depn
sudo docker build -t yourusername/ros-base:0.1 -f Dockerfile-base .
After the build is complete you can create another docker file from this base image.
FROM yourusername/ros-base:0.1
RUN apt-get install dep1 dep2 depn
Now build the second images:
sudo docker build -t yourusername/mymoveApplication:0.1 -f Dockerfile-base .
Now you have an image for your move application, each container that you run from this image will have all the dependencies installed.
You can have docker image repository for managing your built images and sharing between people/environments.
This example can be expanded multiple times.

Install a package manager inside docker container for images like 'prom/busybox'

I'm trying to troubleshoot one of my running containers, which is based on image 'prom/busybox'
I wanted to install some packages like curl, etc. This image has no default package managers like apk or apt installed. I tried looking for some way to do that, but was not successful. Any hints to do this are most welcome.
You can use other busybox images like https://github.com/progrium/busybox
There you can install those:
FROM progrium/busybox
RUN opkg-install curl bash git
CMD ["/bin/bash"]

Is it possible to remove unwanted packages from docker image?

I'm trying to reduce the size of my docker image which is using Centos 7.2
The issue is that it's 257MB which is too high...
I have followed the best practices to write Dockerfile in order to reduce the size...
Is there a way to modify the image after the build and rebuild that image to see the size reduced ?
First of all if you want to reduce an OS size, don't start with big one like CentOS, you can start with alpine which is small
Now if you are still keen on using CentOS, do the following:
docker run -d --name centos_minimal centos:7.2.1511 tail -f /dev/null
This will start a command in the background. You can then get into the container using
docker exec -it centos_minimal bash
Now start removing packages that you don't need using yum remove or yum purge. Once you are done you can commit the image
docker commit centos_minimal centos_minimal:7.2.1511_trial1
Experimental Squash Image
Another option is to use an experimental feature of the build command. In this you can have a dockerfile like below
FROM centos:7
RUN yum -y purge package1 package2 package2
Then build this file using
docker build --squash -t centos_minimal:squash .
For this you need to add "experimental": true to your /etc/docker/daemon.json and then restart the docker server
It is possible, but not at all elegant. Just like you can add software to the base image, you could also remove:
FROM centos:7
RUN yum -y update && yum clean all
RUN yum -y install new_software
RUN yum -y remove obsolete_software
Ask yourself: does your OS have to be CentOS? Then I would recommend you use the default installation and make sure your have enough disk space and memory.
If it does not need to be CentOS, you should rather start with a more minimalistic image. See the discussion here:
Which Docker base image should be used to install Apps in a container without any additional OS?

Resources