Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Docker Quickstart

Eli Barzilay edited this pageMay 28, 2021 ·2 revisions

Using Docker, the short, short version

"Short" is not a joke, it's because I used many examples which is whythis text is much longer than what you need. To make it short, findthe first example that fits your needs and use it.

Quick highlevel overview

Docker is essentially a way to run stuff in a local sandboxedenvironment. The environment is specified by adocker image, and itsmain component is a snapshot of all files that are needed to run in, inthe form of "layers", each saved as a tar archive (and it's implementedasUnionFS).

Docker is not a VM, but often confused as one. Images arelinux-based, and therefore Docker on Windows works by installing atiny Hyper-V Linux VM to run on (but that is shared for all dockeruses, it's not starting a VM for each run).

When you run an image, the running sandbox is called acontainer.These container are based on the image which is the initial state (filesetc), and on top of that there are any changes that the currentexecution created (FS changes, running process/es, etc). When containeris done running,all of that usually disappears, making it veryconvenient to run random stuff without affecting your setup. (It ispossible to save containers, but usually they're removed after use.)

Quick examples

You need toinstalldocker to try thefollowing examples. The installer itself is generally well behaved andwill tell you what needs to be done to make it work (eg, turning onwindows features like hyper-v or the wsl2 backend). There are alsoinstallers for macs and for linux (the latter being a system daemonrather than a tiny vm).

Once installed, you can use thedocker command to do stuff. It hasthe usualdocker 〈verb〉 args... format. On windows, it works finein all forms: powershell, vscode, and even in a cmd box. The main (andpossibly the only) verb you need to know about isrun:

docker run -it --rm node

This drops you into a runningnode container. (Ctrl+D is thecanonical EOF-thing in unix, use it to exit the running process andtherefore the container.)

  • run: start running a container for the specified image. The imagewill be pulled in on first use.

  • -it: interactive run (short for--interactive --tty, the latter isa unix thing)

  • --rm: delete the container when done (you can drop this if you wantto keep the results, but usually you want to include it)

  • node: the name of the image we want to run (there aremany, enough that most random guesses for"the thing you want to try" will work)

docker run -it --rm node:12

Image names are tagged — this is similar to the above, but now I'mspecifying that I want to use the12 tag. When you don't specify atag as in the above, you get the default of:latest.

Tags are not permanently fixed (especially notlatest). To update atag (eg, a new node version is published), you can usedocker pull node to update it. Similarly,node:12 is a tag that points at themost recent 12.x version.

But this is still just drops you into a runningnode, what if you wantto do something before starting it, like installing some suspiciouspackage?

docker run -it --rm node bash

Here I added abash at the end, overriding what thenode image runsby default. Now I get abash prompt, and I can do whatever I want:npm install stuff (locally or globally),apt install OS packages(you'll need toapt update first to get the package directory), andevenrm /bin/* — it's all completely safe, and everything willdisappear when the container is done.

But if you know even a little about linux, you'll recognize that this isa kind of an overkill: you start at the root of the filesystem, and astheroot user. This could be significantly different from actual use.For example, I run into a weird new1line-aa npm package, with novisible information about how it's working, and I want to try it as auser.

docker run -it --rm node bash$ su -l node$ npm install 1line-aa

One way to do this is to runsu -l node in the container, which startsa new shell for thenode user (which the node image includes). Sincethis process is started from the first one, you'll need to Ctrl+D twiceto get out of the container (or thrice if you startnode).

docker run -it --rm -u node -w /home/node node bash

Another way to do this directly is to add:

  • -u node: start as thenode user

  • -w /home/node: in its home directory

So far all of these examples left nothing behind, but what if youwantto collect some of the resulting files?

docker run -it --rm -v c:\foo:/work node bash
  • -v c:\foo:/work: mount thec:\foo directory onto/work in thecontainer

This means that in the container you cancd /work and do whatever youwant there: since it's a mounted directory, everything will actuallyhappen in yourc:\foo directory (which will be created if it doesn'texist). It doesn't matter that the file owner inside the container isroot, since on a Windows host side, it's all running as your Windowsuser. This isnot the case if you're using docker on linux: in thatcase,root in the container will create files that belong toroot onthe host. In any case, switching to thenode user (as done above) ispreferable.

Complicated example 1: tsserverfuzzer

This is a more involved example: running thefuzzer. First, clone therepository — thenode image includesgit so you can do it in thecontainer, but you're probably more comfortable with your usualenvironment. You'll probably use vscode or whatever... something like

c:\> cd workC:\work> git clone ...tsserverfuzzer...C:\work> cd tsserverfuzzerC:\work\tsserverfuzzer> docker run -it --rm -v %cd%:/fuzzer -w /fuzzer -u node node bash
  • -it --rm: interactive, dispose after use

  • -v %cd%:/fuzzer: mount the current directory as/fuzzer in thecontainer (in powershell, use$pwd instead of%cd%)

  • -w /fuzzer: and work in there

  • -u node: as thenode user

node@...:/fuzzer$ npm install...node@...:/fuzzer$ npm run build...node@...:/fuzzer$ git status...node@...:/fuzzer$ node lib/Fuzzer/main.js

You can now do the usual things, evengit commands (since the fileformat is the same — just be careful of sneaky EOL translation).

I you did all of this, thegit status should show just a change inpackage-lock.json, and the last execution got stuck waiting for adebugger to connect. Ctrl+C to abort it, and Ctrl+D to exit thecontainer.

docker run ...same... -p 9229:9242 node bash

It's possible to forward ports from the container to the host, and it'ssimilar to the-v flag with the same meaning to the two sides of thecolon: here we're saying that port 9242 in the container is exposed asport 9229 on the host. Once you do that, you can skip the building(since the built files are still in the directory on your host) and gostraight to thenode command.

... except that this won't work either. This is because the debuggerlistens on127.0.0.1:9242 (and it tells you that), which means that itonly accepts connections fromlocalhost which is the container. We'reconnecting from what looks to the container like a different machine, sowe need to allow that. To do this, openC:\work\tsserverfuzzer\Fuzzer\main.ts in your editor (outside thecontainer!) and change'--inspect-brk=9242' to'--inspect-brk=0.0.0.0:9242' (the0.0.0.0 tells it to listen toanyone).

The container sees the file modification, so you don't need to restartit, you can just runnpm build again, and re-run.

docker run ...same... node node lib/Fuzzer/main.js

When you want to run the already-built fuzzer later, you can start itdirectly. Thenode node looks confusing, but the first one is thename of the image, and following it is thenode command that you wantto run in the container instead of starting an interactive repl.

docker run ...same... -e GitHubAuthenticationKey=%tok% node node lib/Fuzzer/main.js

At some point you'll find that it needs a GH key in the$GitHubAuthenticationKey environment variable. The-e VAR=VAL flagsets such a value, and in this case we're using a Windows%tok% as thevalue. (And something like$env:tok in powershell.)

Since it's running the node code directly, a Ctrl+C will stop it andexit the container immediately.

Complicated example 2: TypeScriptErrorDeltas

There's enough verbiage above to run it, but a few more useful bits thatare relevant in this case:

docker run ... -v %USERPROFILE%\.npmrc:/home/node/.npmrc:ro ...

You'll find that you need an npm authentication key to be able tonpm install this thing. Assuming that you have the key in yourC:\Users\foo\.npmrc, you can re-use your.npmrc in the container.There are two new things here:

  • Container mounts don't have to be directories, you can mount a singlefile as this is doing.

  • An access mode can follow a second:, userw (the default) forread-write orro read-only. In this example using:ro ensuresthat the container cannot modify the windows.npmrc file.

C:\...> docker run -it --rm ... node bash# apt update; apt install sudo# node /work/index.js 1 3.3 3.4 false

One problem with running this code is that it requires havingsudo,but thenode image is based on a minimal linux so it doesn't have it.One way to do it is to fix the code to not usesudo if it's running asroot ... but a way around it is to start the container withbash, andrun the twoapt commands to getsudo installed. (In the case ofthisTypeScriptErrorDeltas code, there is something else that isneeded: see "Privileged runs" below.)

It is obviously tedious to do this installation every time you want torun it — ignoring changing the code to not require extra packages, it ispretty easy to build an image yourself. But I'll finish the quick parthere.

Extras

Privileged runs

A docker container is an image running in a sandboxed environment thatis restricted in several ways (like seeing its own FS and network).There are, however, cases where linux functionality is needed from thekernel — and mounting things (when you're alreadyin the container) isone such case that is normally blocked. Docker has a bunch of"capabilities" that are off by default and can be turned on if needed.In cases likeTypeScriptErrorDeltas, where you're running knownnon-malicious code, you can just enable all of them by adding a--privileged flag.

docker build

Thebuild verb can be used with aDockerfile which specifies arecipe for creating an image. For example, it's easy to make an imagethat is based on thenode image, but has a few more os packagesinstalled, and defaults to a specific directory, user, and command torun. There's lots of examples around, but in general I'll be happy toexplain how to create any image that anyone might need.

docker ps

This is a useful command to see a list of running docker containers.Usually this should be empty, but you might press some wrong key (likeCtrl+Z, which suspends a process) and end up with a stray process. Usethis to see such processes, and kill them withdocker rm -f 〈container-id〉.

const orGUI =  "Or, as long as you're a gui-dependent windows user,"  + "just use the docker gui...";

console.log(orGUI);

docker exec

The process that gets to run on adocker run is not the only thingthat runs. Subprocesses can run in the container, of course, but inaddition to that you can start another process in the context of arunning container. This is useful, for example, if you started acontainer as thenode user, and you need to install some os package,but you don't want to start from scratch.

C:\> docker ps... node id ...C:\> docker exec -it 123 bash

To do this, usedocker ps to find your container's id, then usedocker exec to start abash process in it. It is somewhat similartorun except that it expects a running container id. (Or names,since you can name running containers, because why not add features.)

console.log(orGUI);

docker system prune

You might end up with random stuff that sticks around for whateverreason. A running or a suspeded container, stray images since youplayed with building your own image, or whatever.

docker system prune -f

This will remove any such stuffs. The-f makes it just remove theunnecessary stuff rather than ask you for confirmation.

console.log(orGUI);

Want to contribute to this Wiki?

Fork it and send a pull request.

News

Debugging TypeScript

Contributing to TypeScript

Building Tools for TypeScript

FAQs

The Main Repo

Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp