135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
-
+
|
I resorted to that “sleep 3600” hack in order to work around the lack of interactive mode in `container.npk`, without which containers of this type will start, do a whole lot of _nothing_, and then stop. I had to give it some type of busy-work to keep it alive long enough to let me shell in and do my actual work. This sneaky scam is a common one for accomplishing that end, but it has the downside of requiring you to predict how long you want the container to run before stopping; this version only lasts an hour.
If you are imagining more complicated methods for keeping containers running in the background when they were designed to run interactively, you are next liable to fall into the trap that…
# <a id="cmd"></a>There Is No Host-Side Command Line Parser
The RouterOS CLI isn’t a Bourne shell, and the container feature treats the optional `entrypoint` and `cmd` values as simple strings, without any of the parsing you get for free when typing `docker` commands into a Linux command shell. The net effect of all this is that you’re limited to two-word commands, one in `entrypoint` and the other in `cmd`, as in the above “`sleep 3600`” hack.
The RouterOS CLI isn’t a Bourne shell, and the container feature treats the optional `entrypoint` and `cmd` values as simple strings, without any of the parsing you get for free when typing `docker` commands into a Linux command shell. The net effect of all this is that with many containers, you’re limited to two-word commands, one in `entrypoint` and the other in `cmd`, as in the above “`sleep 3600`” hack.
But how then do you say something akin to the following under RouterOS?
docker run -it alpine:latest ls -lR /etc
You might want to do that in debugging to find out what a given config file is called and exactly where it is in the hierarchy so that you can target it with a `mount=…` override. If you try to pass it all as…
|
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
+
+
+
+
+
+
|
Things aren’t always this grim. For instance, you can run [my `iperf3` container](/dir/iperf3) as a client instead of its default server mode by saying something like:
/container/add … cmd="-c192.168.88.99"
This relies on the fact that the `iperf3` command parser knows how to break the host name part out from the `-c` option itself, something not all command parsers are smart enough to do. There’s 50 years of Unix and Linux history encouraging programs to rely on the shell to do a lot of work before the program’s `main()` function is even called. The command line processing that `container.npk` applies to its `cmd` argument lacks all that power. If you want Bourne shell parsing of your command line, you have to set it via `ENTRYPOINT` or `CMD` in the `Dockerfile`, then rebuild the image.
There is one big exception to all this: a common pattern is to have the `ENTRYPOINT` to a container be a shell script and for that to do something like this at the end:
/path/to/actual/app $@
This ropes the `/bin/sh` inside the container into the process, and depending on exactly how it’s done, it might be able to split a single passed command argument string into multiple arguments to the internal program. The main problem with this is that it’s entirely contingent on how the container image is set up. The only way to profit from this realization other than by happenstance is if you’re creating the image yourself and can arrange for it to run your passed argument string through an interpretation process akin to the one shown above. That amounts to a type of “command injection” vulnerability, but as long as you’re certain your commands are coming from trusted sources, it might be a risk you’re willing to accept.
# <a id="terminal"></a>Interactive Terminal Handling
Although RouterOS proper is built atop Linux, and it provides a feature-rich CLI, it is nothing like a Linux command shell. I am not speaking of skin-level command syntax differences here; the differences go far deeper.
When you SSH into a RouterOS box, you’re missing out on a meaningful distinction between stdout and stderr, and the kernel’s underlying termios/pty subsystem is hidden from you. These lacks translate directly into limitations in the ability of `container.npk` to mimic the experience of using Docker at the command line.
|