Skip to content

Commit 0722883

Browse files
authored
Merge pull request #11 from grycap/showoutput
add showoutput to strace and includefolder to scripts
2 parents c5dd428 + 00938f8 commit 0722883

File tree

17 files changed

+199
-59
lines changed

17 files changed

+199
-59
lines changed

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
When you run containers (e.g. in Docker), you usually run a system that has a whole Operating System, documentation, extra packages, etc. and your specific application. The result is that the footprint of the container is bigger than needed.
44

5-
**minicon** aims at reducing the footprint of the Docker containers, by just including in the container those files that are needed. That means that the other files in the original container are removed.
6-
75
**minicon** is a general tool to analyze applications and executions of these applications to obtain a filesystem that contains all the dependencies that have been detected. In particular, it can be used to reduce Docker containers. The **minicon** package includes **minidock**
86
which will help to reduce Docker containers by hiding the underlying complexity of running **minicon** inside a Docker container.
97

10-
The purpose of **minicon** and **minidock** is better understood with the use cases explained in depth in the section "[Examples](#4-examples)": the size of a basic UI that contains bash, ip, wget, ssh, etc. commands is _reduced from 211MB to 10.9MB_; the size of a NodeJS application along with the server is _reduced from 686 MB (using the official node image) to 45.6MB_; the size of an Apache server is _reduced from 216MB to 50.4MB_, and the size of a Perl application in a Docker container is _reduced from 206MB to 43.3MB_.
8+
The purpose of **minicon** and **minidock** is better understood with the use cases explained in depth in the section "[Examples](#4-examples)": the size of a basic UI that contains bash, ip, wget, ssh, etc. commands is _reduced from 211MB to 10.9MB_; the size of a NodeJS application along with the server is _reduced from 686 MB (using the official node image) to 45.6MB_; the size of an Apache server is _reduced from 216MB to 50.4MB_, and the size of a Perl application in a Docker container is _reduced from 206MB to 5.81MB_.
119

1210
> [**minidock**](doc/minidock.md) is based on [**minicon**](doc/minicon.md), [**importcon**](doc/importcon.md) and [**mergecon**](doc/mergecon.md), and hides the complexity of creating a container, mapping minicon, guessing parameters such as the entrypoint or the default command, creating the proper commandline, etc.
1311
@@ -399,8 +397,8 @@ We can check the differences in the sizes:
399397
```bash
400398
$ docker images minicon
401399
REPOSITORY TAG IMAGE ID CREATED SIZE
402-
minicon uc6 7c85b5a104f5 5 seconds ago 43.3MB
400+
minicon uc6 7c85b5a104f5 5 seconds ago 5.81MB
403401
minicon uc6fat 1c8179d3ba94 4 hours ago 206MB
404402
```
405403

406-
In this case, the size has been reduced from 206MB to about 43.3MB.
404+
In this case, the size has been reduced from 206MB to about 5.81MB.
File renamed without changes.
File renamed without changes.

doc/man/minicon renamed to doc/man/minicon.1

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ to check the dependencies of an application or library. The resulting dependenci
100100
.SS scripts
101101
This plugins tries to guess if a command is an interpreted script. If it is guessed to be, the interpreter will be also analyzed. It makes use of the command
102102
.I file
103-
and the analysis of the shebang line of text files.
103+
and the analysis of the shebang line of text files. It accepts the next optional parameter:
104+
105+
.B includefolders
106+
If it is set to true, the scripts plugin will include in the final filesystem the whole folders in which the interpreter will search for packages (i.e. using @inc or include). The default value is
107+
.B false.
108+
.B 3.
104109

105110
.SS strace
106111
This plugin analyzes the execution of an application and detects which files have been used. It is tightened to the
@@ -110,17 +115,28 @@ parameter from minicon. It accepts several parameters and the syntax is:
110115
--plugin=strace:param=value:param=value...
111116

112117
.B seconds
113-
the number of seconds that strace will be analyzing the execution
118+
the number of seconds that strace will be analyzing the execution. The default value is
119+
.B 3.
114120

115121
.B mode
116-
decides which files will be included in the filesystem. The possible values are: skinny (includes only the opened, checked, etc. files and creates the opened, checked, etc. folders), slim (also includes the whole opened or created folders), regular (also includes the whole folder in which the opened files are stored; useful for included libraries) and loose (also includes the whole opened, checked, etc. folder).
122+
decides which files will be included in the filesystem. The possible values are: skinny (includes only the opened, checked, etc. files and creates the opened, checked, etc. folders), slim (also includes the whole opened or created folders), regular (also includes the whole folder in which the opened files are stored; useful for included libraries) and loose (also includes the whole opened, checked, etc. folder). The default value is
123+
.B skinny.
117124

118125
.B execfile
119126
points to a file that includes commandline examples of different applications. These commandlines will be used for analyzing the executables. E.g. analyzing a plain
120127
.I ping
121128
command has no sense, because it does nothing. But analyzing
122129
.I ping www.google.es
123-
makes use of libraries, name resolution, etc.
130+
makes use of libraries, name resolution, etc. The default value is
131+
.B none.
132+
133+
.B showoutput
134+
If set to
135+
.I true
136+
, strace will output the output of the simulations to stdout and stderr. Otherwise, the simulation is hidden. If it the parameter appears without value, it will be interpreted to be
137+
.I true
138+
(i.e. `--plugin=strace:showoutput` is the same than `--plugin=strace:showoutput=true`). The default value is
139+
.B false.
124140

125141
.SH EXAMPLES
126142

@@ -139,7 +155,7 @@ Then it is possible to import such filesystem into Docker with a command like
139155
The same run of minicon, but running it inside a Docker ubuntu-based container:
140156

141157
.RS 3
142-
.B docker run --privileged --rm -it -v /bin/minicon:/tmp/minicon -v $PWD:/tmp/work ubuntu:latest bash -c 'apt-get install -y strace && /tmp/minicon/minicon -t /tmp/work/minimal.tar --plugin=strace -E bash -E "ssh localhost" -E "ip addr" -E id -E cat -E ls -E mkdir -E "ping -c 1 www.google.es" -- wget -q -O- www.google.es'
158+
.B docker run --cap-add SYS_PTRACE --rm -it -v /bin/minicon:/tmp/minicon -v $PWD:/tmp/work ubuntu:latest bash -c 'apt-get install -y strace && /tmp/minicon/minicon -t /tmp/work/minimal.tar --plugin=strace -E bash -E "ssh localhost" -E "ip addr" -E id -E cat -E ls -E mkdir -E "ping -c 1 www.google.es" -- wget -q -O- www.google.es'
143159
.RE
144160

145161

File renamed without changes.

doc/minicon.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,15 @@ $ ./minicon -t tarfile --plugin=strace:seconds=10 -E '/usr/games/cowsay hello'
155155
# The next execution will try to execute the application bash for 3 seconds (the default value), but will exclude any file used by the application that is found either in /dev or /proc
156156
$ ./minicon -t tarfile --plugin=strace:exclude=/dev:exclude=/proc bash
157157
```
158+
**Parameters**
159+
160+
* _seconds_: The number of seconds while the simulation of the application will be ran. The execution may end earlier, but if not, it will be killed (with -9 signal). The default value is **3**.
161+
162+
* _execfile_: A file that contains examples of command invocation for applications. If an application is tried to be simulated without arguments, the strace plugin will search in this file for a better example. The default value is **None**.
163+
164+
* _mode_: decides which files will be included in the filesystem. The possible values are: _skinny_ (includes only the opened, checked, etc. files and creates the opened, checked, etc. folders), _slim_ (also includes the whole opened or created folders), _regular_ (also includes the whole folder in which the opened files are stored; useful for included libraries) and _loose_ (also includes the whole opened, checked, etc. folder). The default value is **skinny**.
165+
166+
* _showoutput_: If set to _true_, strace will output the output of the simulations to stdout and stderr. Otherwise, the simulation is hidden. If it the parameter appears without value, it will be interpreted to be _true_ (i.e. `--plugin=strace:showoutput` is the same than `--plugin=strace:showoutput=true`). The default value is **false**.
158167

159168
#### scripts plug-in
160169
Some of the executables that you want to include in the resulting filesystem can be scripts (e.g. bash, perl, python, etc.). As an example, **minicon** is a bash script. The problem is that these scripts need an interpreter (i.e. bash is needed for **minicon**), but inspecting the executable using _ldd_ will not find any dependency.
@@ -168,6 +177,10 @@ To activate the strace plugin you can use the option ```--plugin```. Some exampl
168177
$ ./minicon -t tarfile --plugin=scripts ./minicon
169178
```
170179

180+
**Parameters**
181+
182+
* _includefolders_: If it is set to true, the scripts plugin will include in the final filesystem the whole folders in which the interpreter will search for packages (i.e. using _@inc_ or _include_). The default value is **false**.
183+
171184
> **DISCLAIMER**: take into account that the _scripts_ plugin is an automated tool and tries to make its best. If a interpreter is detected, all the default include folder for that interpreter will be added to the final filesystem. If you know your app, you can reduce the number of folders to include.
172185
173186
## 4. Use Cases
@@ -334,7 +347,7 @@ minicon uc2fat 2a95d52068fd 2 minutes ago
334347
But we can reduce the size, if we know which tools we want to provide to our users. From the folder in which it is installed **minicon**, we can execute the following commands to minimize the container and to import it into docker:
335348

336349
```
337-
$ docker run --privileged --rm -it -v /home/calfonso/Programacion/git/minicon:/tmp/minicon minicon:uc2fat bash -c 'apt-get install -y strace && /tmp/minicon/minicon -t /tmp/minicon/usecases/uc2/uc2.tar --plugin=strace:execfile=/tmp/minicon/usecases/uc2/execfile-cmd -E bash -E ssh -E ip -E id -E cat -E ls -E mkdir -E ping -E wget'
350+
$ docker run --cap-add SYS_PTRACE --rm -it -v /home/calfonso/Programacion/git/minicon:/tmp/minicon minicon:uc2fat bash -c 'apt-get install -y strace && /tmp/minicon/minicon -t /tmp/minicon/usecases/uc2/uc2.tar --plugin=strace:execfile=/tmp/minicon/usecases/uc2/execfile-cmd -E bash -E ssh -E ip -E id -E cat -E ls -E mkdir -E ping -E wget'
338351
$ docker import usecases/uc2/uc2.tar minicon:uc2
339352
```
340353

doc/minidock.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ When you run Docker containers, you usually run a system that has a whole Operat
44

55
**minidock** aims at reducing the footprint of the Docker containers, by just including in the container those files that are needed. That means that the other files in the original container are removed.
66

7-
The purpose of **minidock** is better understood with the use cases explained in depth in the section "[Examples](#4-examples)": the size of an Apache server is reduced from 216MB. to 50.4MB., and the size of a Perl application in a Docker container is reduced from 206MB to 50.4MB.
7+
The purpose of **minidock** is better understood with the use cases explained in depth in the section "[Examples](#4-examples)": the size of an Apache server is reduced from 216MB. to 50.4MB., and the size of a Perl application in a Docker container is reduced from 206MB to 5.81MB.
88

99

1010
> **minidock** is based on [**minicon**](minicon.md), [**importcon**](importcon.md) and [**mergecon**](mergecon.md), and hides the complexity of creating a container, mapping minicon, guessing parameters such as the entrypoint or the default command, creating the proper commandline, etc.
@@ -323,7 +323,7 @@ minicon uc5fat ff6f2573d73b 9 days ago
323323

324324
In order to reduce it, you just need to issue the next command:
325325
```bash
326-
$ ./minidock -i minicon:uc5fat -t minicon:uc5 --apt
326+
$ minidock -i minicon:uc5fat -t minicon:uc5 --apt
327327
...
328328
```
329329

@@ -378,7 +378,7 @@ $ docker run --rm -it minicon:uc6fat i am a cow in a fat container
378378
In this case, the entrypoint needs some parameters to be run. If you try to analyze the container simply issuing a command like the next one:
379379

380380
```bash
381-
$ ./minidock -i minicon:uc6fat -t minicon:uc6 --apt
381+
$ minidock -i minicon:uc6fat -t minicon:uc6 --apt
382382
...
383383
$ docker run --rm -it minicon:uc6 i am a cow in a not properly minimized container
384384
cowsay: Could not find default.cow cowfile!
@@ -389,7 +389,7 @@ It does not work properly, because the execution of the entrypoint has not been
389389
In this case, you should run a **minidock** commandline that include the command that we used to test it, and we will be able to run it:
390390

391391
```bash
392-
$ ./minidock -i minicon:uc6fat -t minicon:uc6 --apt -- i am a cow in a fat container
392+
$ minidock -i minicon:uc6fat -t minicon:uc6 --apt -- i am a cow in a fat container
393393
...
394394
$ docker run --rm -it minicon:uc6 i am a cow in a minimized container
395395
_____________________________________
@@ -409,11 +409,11 @@ We can check the differences in the sizes:
409409
```bash
410410
$ docker images minicon
411411
REPOSITORY TAG IMAGE ID CREATED SIZE
412-
minicon uc6 7c85b5a104f5 5 seconds ago 43.3MB
412+
minicon uc6 7c85b5a104f5 5 seconds ago 5.81MB
413413
minicon uc6fat 1c8179d3ba94 4 hours ago 206MB
414414
```
415415

416-
In this case, the size has been reduced from 206MB to about 43.3MB.
416+
In this case, the size has been reduced from 206MB to about 5.81MB.
417417

418418
# 5. Flexible Manipulation of Container Filesystems
419419

importcon

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ function trim() {
200200
function build_cmdline() {
201201
local SHCMDLINE=""
202202
while [ $# -gt 0 ]; do
203-
if [ "$1" == "&&" -o "$1" == ">" -o "$1" == ">>" -o "$1" == "2>" -o "$1" == "2>>" -o "$1" == "<" -o "$1" == "<<" ]; then
203+
if [ "$1" == "|" -o "$1" == "&&" -o "$1" == ">" -o "$1" == ">>" -o "$1" == "2>" -o "$1" == "2>>" -o "$1" == "<" -o "$1" == "<<" ]; then
204204
SHCMDLINE="${SHCMDLINE} $1"
205205
else
206206
SHCMDLINE="${SHCMDLINE} \"$1\""
@@ -219,10 +219,21 @@ function arrayze_cmd() {
219219
local _CMD="$2"
220220
local R n=0
221221
while read R; do
222-
read ${AN}[n] <<< "$R"
222+
read ${AN}[$n] <<< "$R"
223223
n=$((n+1))
224224
done < <(printf "%s\n" "$_CMD" | xargs -n 1 printf "%s\n")
225225
}
226+
227+
function lines_to_array() {
228+
local AN="$1"
229+
local LINES="$2"
230+
local L
231+
local n=0
232+
while read L; do
233+
read ${AN}[$n] <<< "$L"
234+
n=$((n+1))
235+
done <<< "$LINES"
236+
}
226237
function generate_dockerimagename() {
227238
local NEWNAME
228239
NEWNAME="$(cat /proc/sys/kernel/random/uuid)"
@@ -274,7 +285,7 @@ function get_config_field_raw() {
274285
echo "$(trim "$C_RESULT")"
275286
}
276287

277-
VERSION=1.2-1
288+
VERSION=1.2-2
278289

279290
n=0
280291
while [ $# -gt 0 ]; do

mergecon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ function get_config_field_raw() {
228228
echo "$(trim "$C_RESULT")"
229229
}
230230

231-
VERSION=1.2-1
231+
VERSION=1.2-2
232232

233233
function verify_dependencies() {
234234
if ! docker --version > /dev/null 2> /dev/null; then

minicon

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ function trim() {
268268
function build_cmdline() {
269269
local SHCMDLINE=""
270270
while [ $# -gt 0 ]; do
271-
if [ "$1" == "&&" -o "$1" == ">" -o "$1" == ">>" -o "$1" == "2>" -o "$1" == "2>>" -o "$1" == "<" -o "$1" == "<<" ]; then
271+
if [ "$1" == "|" -o "$1" == "&&" -o "$1" == ">" -o "$1" == ">>" -o "$1" == "2>" -o "$1" == "2>>" -o "$1" == "<" -o "$1" == "<<" ]; then
272272
SHCMDLINE="${SHCMDLINE} $1"
273273
else
274274
SHCMDLINE="${SHCMDLINE} \"$1\""
@@ -287,10 +287,21 @@ function arrayze_cmd() {
287287
local _CMD="$2"
288288
local R n=0
289289
while read R; do
290-
read ${AN}[n] <<< "$R"
290+
read ${AN}[$n] <<< "$R"
291291
n=$((n+1))
292292
done < <(printf "%s\n" "$_CMD" | xargs -n 1 printf "%s\n")
293293
}
294+
295+
function lines_to_array() {
296+
local AN="$1"
297+
local LINES="$2"
298+
local L
299+
local n=0
300+
while read L; do
301+
read ${AN}[$n] <<< "$L"
302+
n=$((n+1))
303+
done <<< "$LINES"
304+
}
294305
function plugin_parameter() {
295306
# Gets the value of a parameter passed to a plugin
296307
# the format is: <plugin>:<param1>=<value1>:<param2>=<value2>...
@@ -578,6 +589,14 @@ function _strace_exec() {
578589
SECONDSSIM=3
579590
fi
580591

592+
local SHOWSTRACE
593+
SHOWSTRACE=$(plugin_parameter "strace" "showoutput")
594+
if [ $? -eq 0 ]; then
595+
if [ "$SHOWSTRACE" == "" ]; then
596+
SHOWSTRACE=true
597+
fi
598+
fi
599+
581600
local MODE
582601
MODE="$(_strace_mode)"
583602

@@ -588,9 +607,13 @@ function _strace_exec() {
588607
p_info "analysing ${COMMAND[@]} using strace and $SECONDSSIM seconds ($MODE)"
589608

590609
local TMPFILE=$(tempfile)
591-
{
592-
timeout -s 9 $SECONDSSIM strace -qq -e file -fF -o "$TMPFILE" "${COMMAND[@]}" > /dev/null 2> /dev/null
593-
} > /dev/null 2> /dev/null
610+
if [ "$SHOWSTRACE" == "true" ]; then
611+
timeout -s 9 $SECONDSSIM strace -qq -e file -fF -o "$TMPFILE" "${COMMAND[@]}"
612+
else
613+
{
614+
timeout -s 9 $SECONDSSIM strace -qq -e file -fF -o "$TMPFILE" "${COMMAND[@]}" > /dev/null 2> /dev/null
615+
} > /dev/null 2> /dev/null
616+
fi
594617

595618
# Now we'll inspect the files that the execution has used
596619
local EXEC_FUNCTIONS="exec.*"
@@ -767,7 +790,7 @@ function STRACE_command() {
767790
fi
768791
CMDLINE[0]="$COMMAND"
769792
fi
770-
COMMAND=( ${CMDLINE[@]} )
793+
COMMAND=( "${CMDLINE[@]}" )
771794
_strace_exec
772795

773796
PLUGINS_ACTIVATED="${_PLUGINS_ACTIVATED}"
@@ -780,6 +803,17 @@ function PLUGIN_11_scripts() {
780803
# If it is, adds the interpreter to the list of commands to add to the container
781804
p_debug "trying to guess if $1 is a interpreted script"
782805

806+
local INCLUDEFOLDERS
807+
INCLUDEFOLDERS=$(plugin_parameter "scripts" "includefolders")
808+
if [ $? -eq 0 ]; then
809+
if [ "$INCLUDEFOLDERS" == "" ]; then
810+
INCLUDEFOLDERS=true
811+
fi
812+
else
813+
# The default value is to include the folders that the interpreter may use
814+
INCLUDEFOLDERS=false
815+
fi
816+
783817
local S_PATH="$(which $1)"
784818
local ADD_PATHS=
785819

@@ -812,10 +846,8 @@ function PLUGIN_11_scripts() {
812846
fi
813847

814848
case "$(basename "$INTERPRETER")" in
815-
perl) ADD_PATHS="${ADD_PATHS}
816-
$(perl -e "print qq(@INC)" | tr ' ' '\n' | grep -v -e '^/home' -e '^\.')";;
817-
python) ADD_PATHS="${ADD_PATHS}
818-
$(python -c 'import sys;print "\n".join(sys.path)' | grep -v -e '^/home' -e '^\.')";;
849+
perl) ;;
850+
python) ;;
819851
bash) ;;
820852
sh) ;;
821853
env) ADD_PATHS="${ADD_PATHS}
@@ -824,6 +856,16 @@ ${ENV_APP}";;
824856
return 0;;
825857
esac
826858

859+
# If we want to include the 'include' folders of the scripts (to also include libraries), let's get them
860+
if [ "$INCLUDEFOLDERS" == "true" ]; then
861+
case "$(basename "$INTERPRETER")" in
862+
perl) ADD_PATHS="${ADD_PATHS}
863+
$(perl -e "print qq(@INC)" | tr ' ' '\n' | grep -v -e '^/home' -e '^\.')";;
864+
python) ADD_PATHS="${ADD_PATHS}
865+
$(python -c 'import sys;print "\n".join(sys.path)' | grep -v -e '^/home' -e '^\.')";;
866+
esac
867+
fi
868+
827869
if [ "$ADD_PATHS" != "" ]; then
828870
p_debug "found that $S_PATH needs $ADD_PATHS"
829871
local P
@@ -846,7 +888,7 @@ function plugin_list() {
846888
done <<< "$(PLUGIN_funcs)"
847889
echo
848890
}
849-
VERSION=1.2-1
891+
VERSION=1.2-2
850892

851893
function is_protected() {
852894
local SRC="$1"

0 commit comments

Comments
 (0)