Alpine

Lab 0x1

Review 

Goal: A containerized C development environment

Review: Newish:
- podman - Alpine
- vim - Images
- gcc - Copies
- git

Requirements

  • You should have Podman installed.
  • If you are on Windows, you should have WSL installed.
    • I use it with Ubuntu but do what you like.

TODO (windows only)

wsl --install -d ubuntu

Podman 

  • podman is a command, like python
    • Like python we can provide arguments
    • Unlike python we provide further commands, not just a .py file

TODO

podman
  • If this doesn’t work, make sure Podman Desktop is running.
  • If that doesn’t work, make sure you installed Podman Desktop with the Podman Installer.
  • If that doesn’t work, make sure you aren’t a Windows users with WSL installed.
    • Windows users may use Podman within WSL at their discretion.

Run

  • First thing we’ll do in Podman is podman run

TODO

podman run

It should look something like this:

Images

  • The thing we run is called an image
  • We’ll use a sample image named Python
    • You’ll never guess what it does (Python)
  • Students may wish to specify “python:alpine”
    • That is the python command in the alpine operating system.
    • This is a 20x smaller image, so 20x faster download
    • It is on a less common Linux OS (alpine) that may be harder to use.

TODO

podman run python:alpine

It should look something like this:

Just do -it

  • We downloaded an image and ran it as a container but…
    • We didn’t ask the container to do anything
    • So it exits instantly
    • Of note, we only have to download once (image) to run many times (container)
  • To work within the container run -it for “interactive terminal”

TODO

podman run -it python:alpine

It should look something like this:

Alpine 

  • To actually do anything useful in a container, we’d like to:
    • Be able to setup an image once, then use it.
    • Move files into and out of a container.

Containerfiles

This section concerns something called variously “Containerfiles” or “Dockerfiles” - commonly referred to as “Dockerfiles”, though I believe this is changing over time. If you get stuck, it may be easier to look up “Dockerfiles” documentation - I’ve been looking at both.

  • Usually when I’m using a container, I need something for which I can’t simply find a default image.
  • In my case, I specifically want a container with something called a “Containerfile”.
  • Here is a minimal example:
Containerfile
  • I use Alpine as my base image
  • It’s a lightweight Linux operating system
  • It (tends to) have everything I need.

TODO

echo "FROM alpine" > Containerfile
  • I would save “Containerfile” wherever I save classwork.
    • For me, a class-specific directory inside my home directory in the Linux filesystem
      • including on Windows - I work within the WSL filesystem.

Ultimately for me, it looks something like this:

Build

  • With a “Containerfile” written, we can use podman build.

TODO

podman build

It should look something like this:

Pale blue .

  • As with podman run, with podman build we must specify what image to use
    • But now we can use an image described by a “Containerfile”!
  • To specify, we simply give the current directory ..

TODO

podman build .

It should look something like this:

We love the -t

  • This creates a new image but we don’t know what to call it
    • The default name is that numerical value in the 2nd to last time above
  • Use the -t option to podman build, to name the image.
    • As far as I can tell, it stands for “tag”
  • We can then use this image by name with other commands.

TODO

podman build -t crypto .

It should look something like this:

Run

  • The “crypto” image is now being maintained on your device by Podman.
  • We can use run as we did with any other image.

TODO

podman run -it crypto

It should look something like this:

vim

  • First, we can see if we have, say vim. We do not:

TODO

vim

It should look something like this:

apk

  • To add software to Alpine linux, we use apk - the Alpine Package Keeper.

TODO

apk

It should look something like this:

add

  • Generally speaking, we can use add with the name of a command, and apk will find and install that command for us:
    • vim
    • gcc
    • python
      • probably have to say python2 or python3
    • podman
      • can probably run within a container, I didn’t check.

TODO

apk add vim

It should look something like this:

  • To install vim, apk had to install a few other things first…
    • Including the legendary C library ncurses!
    • Used to make legendary game “Rogue”
    • Fun!
  • But ultimately, apk got vim working

vim

  • Test it:

TODO

vim

It should look something like this:

Quick :q

  • That is vim running in podman in a “crypto” folder in my home folder.
  • Let’s get back to home, following back up:
    • ~ (Linux home)
      • ~/crypto (folder name)
        • podman run -it crypto (crypto image run by podman executable)
          • vim (vim executable run by crypto image)
  • We first leave vim

TODO

:q

It should look something like this, with whatever previous commands you used before vim present:

Exit

  • That is vim running in podman in a “crypto” folder in my home folder.
  • Let’s get back to home, following back up:
    • ~ (Linux home)
      • ~/crypto (folder name)
        • podman run -it crypto (crypto image run by podman executable)
  • We then exit the container

TODO

exit

It should look something like this, with whatever previous commands you used before vim present:

Exit

  • We entered a container via run and installed vim.
  • In theory this means we can
    • run, again, then
    • use vim without installing with apk
  • Test it

TODO

podman run -it crypto
vim

It should look like this::

  • We installed vim to a container.
  • We ran an image
  • An image is an instance of the container
    • Nothing done in a container persists post-exit
    • If we want to use vim immediately, we need to add it to the image
  • We’ll exit the container then solve this problem.

TODO

exit

Images

  • We recall:
    • To actually do anything useful in a container, we’d like to:
      • Be able to setup an image once, then use it.
      • Move files into and out of a container.
    • Reference: Dockerfile reference (dockerdocs)
  • To begin, let’s review our “Containerfile”
Containerfile
  • If we wish to use e.g. vim, we have seen this to be insufficent.

RUN

  • “FROM” specifies the base image
    • Our base image the Alpine Linux operating system - and nothing else
  • “RUN” specifies commands to configure the image
    • We know how to use apk to configure containers
    • We can do the same at image-level in the “Containerfile
  • We add our apk command as the argument to “RUN”
  • I made these edits using vim I had installed on my host machine!
Containerfile

Test it

  • It is a simple enough matter to
    • Verify the changes were made with cat
    • Rebuild the image with podman build
    • Run a container of the image image with podman run
    • Test the installation via vim

TODO

  1. podman build -t crypto .
  2. podman run -it crypto
  3. vim file.txt
  4. :q
  5. exit

It should look something like this:

  • To actually do anything useful in a container, we’d like to:
    • ✓ Be able to setup an image once, then use it.
    • Move files into and out of a container.

Copies

  • We recall:
    • To actually do anything useful in a container, we’d like to:
      • ✓ Be able to setup an image once, then use it.
      • Move files into and out of a container.
  • Let’s move some files - or better yet, copy them.

cp for Calvin, Prof.

  • So far, everything we’ve done has been with respect to an image
    • We introduce our first container command - podman cp
    • It is a lot like Linux cp, which is short for copy
    • Actually - let’s practice Linux cp first
  • For practice, we’ll:
    • Make a new sub-folder in our class folder
    • Save a copy of our current “Containerfile” there

TODO

  1. mkdir backup
  2. cp Containerfile backup
  3. ls
  4. cat backup/Containerfile

It should look something like this:

  • I also have installed a command called tree that gives a better view:

ps -a

  • Not public service announcement, but close.
  • podman ps -a lists all the containers that podman has run
    • This is can be n containers per image
      • ps for processes, plural
        • ps is also a Linux command (try it)
        • Hence not cs even though we’re talking about containers
      • -a for “all”
        • Lists active (containers are currently running) and inactive
        • We need this because containers we exit won’t show up otherwise.
  • What you see will depend on how many times you’ve used podman run

TODO

podman ps -a

It should look something like this, depending on previous run commands:

  • We mostly care about the last part - “NAMES”
    • We need to know the name of a container to copy out of it.

It may be helpful to use podman rm -a (again like Linux rm) to remove all containers, and then redo the steps to save a file in a container. Then you’ll only have one container to worry about! It’s what I did.

podman cp

  • podman cp is like Linux cp
    • except we have to use:
      • a container name, and
      • a colon “:”
  • We can copy to or from containers
    • Probably between containers, I didn’t check.
  • Make sure you get the correct container name!
    • Yours will not be flamboyant_feynman
      • Well, maybe, but I doubt it.

TODO

  1. podman cp flamboyant_feynman:/file.txt .
  2. cat file.txt

It should look something like this, depending on what you wrote:

  • To actually do anything useful in a container, we’d like to:
    • ✓ Be able to setup an image once, then use it.
    • ✓ Move files into and out of a container.

Use it

Note

  • This section will be much less explicit and apply what you learned.
    • If you get stuck, check prior sections.
  • If you get stuck, move onto the next section “Git it” to save you work and finish up latter.
    • It contains the answer key

Goal

  • We will:
    • Set up the “crypto” image for C development
      • Write C code
      • Compile C code
      • Run C code
      • Copy the C code back the host system

Hello, World

  • The “K&R C” book that is an optional text for this course begins with an example “hello world” problem in C. They write:
hello.c
  • They were writting in 1988
  • Standards have changed a bit
  • We now try to maintain compatibility with C++,
    • Which really rose into prominence with C++98 (in 1998)
  • Just recently, C23 (for 2023) removed what are called “K&R” functions
  • Basically:
    • We have to specify the return type of a function.
    • The main function must have a return type of int
    • A well-formed program should return numerical zero
hello.c
  • You can use either of these, but gcc will issue a warning for the 1988 version by default.

GCC

  • Prepare GCC
    • Update your “Containerfile” so you may use gcc
    • Build the image
    • Verify you have some gcc version.
  • You will know you have correctly set up GCC when you can do the following:

TODO

podman run -it crypto gcc --version

It should look something like this:

Containerfile COPY

  • Containerfiles may direct containers to copy files from the host device on start-up
  • Save “hello.c” in the same directory as your Containerfile:
user@DESKTOP-THMS2PJ:~/crypto$ tree
.
├── Containerfile
└── hello.c

0 directories, 2 files

Git it

Init

  • Only have to do this once!
  • We initialize our current directory as a git repository
    • Basically this creates a hidden file that tracks changes
    • The presence of this file enables all other git commands.
  • We use the -b modififier to specify the branch
    • We specify the current branch as “main”
    • The default branch, just like the main function in C!

TODO

git init -b main

It should look something like this:

Add

  • We add files to the git repository
    • Files are not included by default
    • Here I will add two by name:
      • Containerfile
      • hello.c

TODO

git add Containerfile hello.c

It should look something like this:

  • We don’t see anything - many git commands are silent.
  • Use git status at any time to learn more.

Commit

  • We add commit changes to the git repository
    • This is like making a version
    • Or like making a container (commit) of a repository (image)
    • Here I will use flag -m to add a commit message
      • Commit messages are mandatory
      • If I don’t specify one, git will open a vim window and I write one there

TODO

git commit -m "First commit"

It should look something like this:

Go to GitHub.com

  • Only have to do this once!
  • At this point, we have to go to GitHub to prepare a repository there.
  • I’m assuming you know how to do this, but if not that’s okay!

Remote

  • Only have to do this once!
  • We link our local repository to the GitHub repository
    • Our local code is the “origin”
      • So we “add origin”
    • We add origin to the url of the GitHub repository we made!
      • Mine was cd-c89/alpine.git
      • You get to pick yours!

TODO

git remote add origin https://github.com/

And add your repository name…

It should look something like this:

Push

  • We take our local version and send it to GitHub
    • All the previous commands were basically preparing a gift to send.
    • Now we send it.
    • There will be logging indicative of network traffic.
    • I don’t usually specify a push from “origin” to “main”
      • Even enough to configure this via git push --set-upstream origin main
      • Git recommends this command if you try to simply git push
      • Only have to set-upstream once!

TODO

git push origin main

It should look something like this:

Closing thoughts

  • This process is longer than normal.
  • Usually I do:
    • (Only add with new files)

TODO

  1. git add ???
  2. git commit -a -m "some message"
  3. git push

FIN