{"id":13566449,"url":"https://github.com/crush-157/smith-lab","last_synced_at":"2026-03-07T18:03:43.466Z","repository":{"id":83949828,"uuid":"111576584","full_name":"crush-157/smith-lab","owner":"crush-157","description":"Introductory hands on lab for Smith ( http://github.com/oracle/smith )","archived":false,"fork":false,"pushed_at":"2018-05-11T07:26:52.000Z","size":22,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-14T15:42:37.180Z","etag":null,"topics":["microcontainers","smith"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crush-157.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2017-11-21T16:53:00.000Z","updated_at":"2021-11-22T22:59:34.000Z","dependencies_parsed_at":"2023-03-05T21:45:15.296Z","dependency_job_id":null,"html_url":"https://github.com/crush-157/smith-lab","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/crush-157/smith-lab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crush-157%2Fsmith-lab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crush-157%2Fsmith-lab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crush-157%2Fsmith-lab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crush-157%2Fsmith-lab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crush-157","download_url":"https://codeload.github.com/crush-157/smith-lab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crush-157%2Fsmith-lab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30225452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T17:00:40.062Z","status":"ssl_error","status_checked_at":"2026-03-07T17:00:39.026Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["microcontainers","smith"],"created_at":"2024-08-01T13:02:09.865Z","updated_at":"2026-03-07T18:03:43.432Z","avatar_url":"https://github.com/crush-157.png","language":null,"funding_links":[],"categories":["Others"],"sub_categories":[],"readme":"# Smith Hands On Exercise\n\n## Introduction\n[Smith](https://github.com/oracle/smith) is a command line tool for building [microcontainers](https://blogs.oracle.com/developers/the-microcontainer-manifesto).\n\nThe aims of this exercise are to walk you through:\n1. Installing Smith\n2. Building a \"hello world\" microcontainer image from scratch\n3. Shrinking an existing container\n\n## Pre - requisites\n- Linux machine (physical or virtual)\n- Editor (vim _obviously_)\n- Docker installed\n- git installed\n- a dockerhub account\n\n## Installing Smith\n### A. As a Docker image\nThe easiest way to install Smith is as a Docker image.  Smith can then be run in a container.\n1. Navigate to [https://github.com/oracle/smith](https://github.com/oracle/smith)\n2. Clone the repo to your machine\n3. Build the Docker image using the Dockerfile provided, adding your own docker-repo-id to the tag:\n\n`sudo docker build -t \u003cdocker-repo-id\u003e/smith .`\n\n4. Create an alias (or script) to run Smith from the command line:\n```\nsmith(){\n    sudo docker run -it --rm \\\n    --privileged -v $PWD:/write \\\n    -v cache:/var/cache \\\n    -v /tmp:/tmp \\\n    -v mock:/var/lib/mock \u003cdocker-repo-id\u003e/smith $@\n}\n```\n5.  Run `smith --version`\n\nIf the response is something like `smith version 1.1.2.22.bc4d01a (built from sha bc4d01a)` then you're in good shape.\n\n### B.  As a binary\n1. Navigate to [https://github.com/oracle/smith](https://github.com/oracle/smith)\n2. Clone the repo to your machine\n3. Install build dependencies (as described in the Smith Readme).\n4. If you're using Debian (or a Debian derived distro), make sure you follow the additional steps for installing mock _(or bad things **will** happen)_\n5. Run `sudo make install`\n6. Run `smith --version`\n\nIf the response is something like `smith version 1.1.2.22.bc4d01a (built from sha bc4d01a)` then you're in good shape.\n\n## Building a \"hello world\" microcontainer from scratch\n1. Create a new directory to build your container in.\n2. Set environment variables for your DOCKER_ID and DOCKER_PWD (as used in the examples below).\n3. Create a smith.yaml file:\n```\npackage: coreutils\npaths:\n- /usr/bin/cat\ncmd:\n- /usr/bin/cat\n- /read/data\n```\n\nThis is to build a microcontainer image from scratch.\n\nStepping through the file:\n\n`package: coreutils` defines as the source.\n```\npaths:\n- /usr/bin/cat\n```\nAdds `/usr/bin/cat` to the microcontainer image.\n```\ncmd:\n- /usr/bin/cat\n- /read/data\n```\nIs a command to `cat` the file `/read/data`.\n\nCreate a subdirectory `rootfs` from your working directory.  Any files or directories placed in here will be appear under root in the image `/`.\n\nSo to add '/read/data' to the image, create a subdirectory `read` of `rootfs`.  Then under read, create a file `data` and put the string you'd like to display (e.g. 'Hello World!') in it.\n\nSo you should have a structure like this:\n```\n[ewan@starbug cat]$ ls -R\n.:\nrootfs  smith.yaml\n\n./rootfs:\nread\n\n./rootfs/read:\ndata\n[ewan@starbug cat]$ cat rootfs/read/data\nHello World!\n```\n\nNow switch back to your working directory and run `smith -i hello.tgz`.\n\nOnce that has finished, you should have a `hello.tgz` file in your working directory.\n\nTo get Docker to run this, we need to upload it to a Docker repo (e.g. dockerhub) to turn it into Docker format (_standards are wonderful when they're implemented_):\n\n`smith upload -r https://$DOCKER_ID:$DOCKER_PWD@registry-1.docker.io/$DOCKER_ID/hello-smith -i hello.tgz`\n\nThen you should be able to run it:\n\n`docker run --rm $DOCKER_ID/hello-smith`\n\nFor example:\n```\newan@starbug:~/projects/smith-examples/cat$ docker run --rm $DOCKER_ID/hello-smith\nUnable to find image 'crush157/hello-smith:latest' locally\nlatest: Pulling from crush157/hello-smith\nca43e03ec88e: Pull complete\nDigest: sha256:eb06aa9738691a7b53f2ee420600be18f473c8fccc40a53a13e683fd40c7f2eb\nStatus: Downloaded newer image for crush157/hello-smith:latest\nHello World!\n```\n**Coffee time :-)**\n\n## Shrinking an existing image\n\nThe image we're going to shrink contains a rudimentary \"ticketing system\" called [Dogsbody](https://github.com/crush-157/dogsbody).  It exists only for the purpose of exercises and labs like this one.\n\nIf you're interested the source code is on [GitHub](https://github.com/crush-157/dogsbody).\n\nThere is already a container image on Docker Hub [crush157/dogsbody](https://hub.docker.com/r/crush157/dogsbody/).\n\nIf you prefer to shrink a different image, then you can just use this as an example.  If you want another example you can also look at [How To Build a Tiny Httpd Container](https://hackernoon.com/how-to-build-a-tiny-httpd-container-ae622c37db39).\n\nThe Dockerfile for the base Dogsbody image is as follows:\n\n```\nFROM ruby\n\nRUN apt-get update\n\n# Install app\nRUN mkdir /app\nWORKDIR /app\nADD ./dogsbody.tgz .\nRUN bundle install\nCMD ./run.sh\n```\n\nIf you pull this down to your machine you'll see that it has a size of 934MB.\n\nNow want to shrink this.\n\n1.  Create another working directory (it's just tidier that way), and cd into it.\n2.  Download the image in OCI format:\n\n```smith download -r https://$DOCKER_ID:$DOCKER_PWD@registry-1.docker.io/crush157/dogsbody -i dogsbody-image.tgz```\n3.  Create a bare bones smith.yaml file:\n```\ntype: oci\npackage: dogsbody-image.tgz\npaths:\n- /app/\n```\n4.  Run smith ```smith -i dogsbody.tar.gz```.  This will create an image with not much in it, but it will also unpack the OCI image for us to have a look around.\n5.  If you look under `/tmp` you will see a directory with a name something like `smith-unpack-1000` (the last part will be your UID so may be different).  In there are the contents of the OCI container.  Let's have a look around for ruby and sinatra:\n```\newan@starbug:/tmp/smith-unpack-1000$ find ./ -name ruby\n./usr/local/bin/ruby\n./usr/local/lib/ruby\n./usr/local/include/ruby-2.4.0/x86_64-linux/ruby\n./usr/local/include/ruby-2.4.0/ruby\newan@starbug:/tmp/smith-unpack-1000$ find ./ -name sinatra\n./usr/local/bundle/gems/sinatra-2.0.0/lib/sinatra\n./usr/local/bundle/gems/mustermann-1.0.1/lib/mustermann/sinatra\n./root/.bundle/cache/compact_index/rubygems.org.443.29b0360b937aa4d161703e6160654e47/info/sinatra\n```\n6.  So lets add some likely looking paths to our smith.yaml, and the command to run the app:\n```\ntype: oci\npackage: dogsbody-image.tgz\npaths:\n- /app/\n- /usr/local/bin/\n- /usr/local/lib/\n- /usr/local/include/\n- /usr/local/bundle/\ncmd:\n- ruby\n- app.rb\n- '-e production'\n```\n7.  Then run `smith -i dogsbody.tar.gz` again to create a new image.\n8.  Let's upload it to docker hub, to get an image in Docker format:\n\n`smith upload -r https://$DOCKER_ID:$DOCKER_PWD@registry-1.docker.io/$DOCKER_ID/smith-dogsbody -i dogsbody.tar.gz`\n\n9. Now let's try and run it.  The first thing we need is a MySQL instance.  If you haven't got one already, then run a MySQL container (change the password / ip / port if you want to):\n```\ndocker run -d --ip 172.17.0.2 -e MYSQL_ROOT_PASSWORD=Welcome_1 --publish 3306:3306/tcp --name dogsbody_db mysql --default-authentication-plugin=mysql_native_password\n```\n\n10.  Then we need to create a database \"dogsbody\".\nIf you're running MySQL in a container, use `docker exec` to access it and create the database:\n```\n$ docker exec -it dogsbody_db bash\n```\nYou should now have a root bash prompt in the container.  Log into the MySQL database.\n```\n# mysql -u root -p \nPassword: \u003ctype MYSQL_ROOT_PASSWORD\u003e\n```\nNow you should have a `mysql\u003e` prompt.  Create the dogsbody database, and then exit the mysql client and the bash shell:\n```\nmysql\u003e create database dogsbody;\nQuery OK, 1 row affected (0.00 sec)\nmysql\u003e exit\n# exit\n```\n\n11.  The next thing we do is run `rake db:migrate` which checks the db schema and updates it if necessary.  Replace the MYSQLCS_* environment variables in the example command below with the appropriate values for your database and then run it:\n```\newan@starbug:~/projects/smith-examples/dogsbody$ docker run -it --rm \\\n\u003e   --name dogsbody \\\n\u003e   --read-only \\\n\u003e   --env MYSQLCS_CONNECT_STRING=\"172.17.0.1:3306/dogsbody\" \\\n\u003e   --env MYSQLCS_USER_PASSWORD=\"Welcome_1\" \\\n\u003e   --env MYSQLCS_USER_NAME=\"root\" \\\n\u003e   $DOCKER_ID/smith-dogsbody rake db:migrate\nMigrating to latest\n```\n12.  If it returned \"Migrating to latest\" you should be good to run the service.  Replace the MYSQLCS_* environment variables in the example command below with the appropriate values for your database and then run it:\n```\newan@starbug:~/projects/smith-examples/dogsbody$ docker run -d --rm \\\n\u003e   --name dogsbody \\\n\u003e   --read-only \\\n\u003e   --env MYSQLCS_CONNECT_STRING=\"172.17.0.1:3306/dogsbody\" \\\n\u003e   --env MYSQLCS_USER_PASSWORD=\"Welcome_1\" \\\n\u003e   --env MYSQLCS_USER_NAME=\"root\" \\\n\u003e   --env PATH=\"/usr/local/bin\" \\\n\u003e   --publish 22222:4567/tcp \\\n\u003e   $DOCKER_ID/smith-dogsbody\n5c7931542a7c5b41ab517b451dac37c8224bcca1fb8d1fbd91989c9a887727dc\n```\n13.  Check that it's running:\n```\newan@starbug:~/projects/smith-examples/dogsbody$ docker ps\nCONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                   PORTS                               NAMES\n5c7931542a7c        crush157/smith-dogsbody     \"ruby app.rb '-e p...\"   36 seconds ago      Up 35 seconds            0.0.0.0:22222-\u003e4567/tcp             dogsbody\n640f14c778ad        mysql/mysql-server:latest   \"/entrypoint.sh my...\"   12 days ago         Up 5 minutes (healthy)   0.0.0.0:3306-\u003e3306/tcp, 33060/tcp   mysql\newan@starbug:~/projects/smith-examples/dogsbody$ curl -v localhost:22222/users\n*   Trying ::1...\n* TCP_NODELAY set\n* Connected to localhost (::1) port 22222 (#0)\n\u003e GET /users HTTP/1.1\n\u003e Host: localhost:22222\n\u003e User-Agent: curl/7.52.1\n\u003e Accept: */*\n\u003e\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: application/json\n\u003c Content-Length: 2\n\u003c X-Content-Type-Options: nosniff\n\u003c Connection: keep-alive\n\u003c Server: thin\n\u003c\n* Curl_http_done: called premature == 0\n* Connection #0 to host localhost left intact\n[]\n```\n200 is what we want.\n\n14.  Let's check the image size:\n```\newan@starbug:~/projects/smith-examples/dogsbody$ docker images\nREPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE\ncrush157/smith-dogsbody    latest              5bbfc75d826b        12 minutes ago      83.4MB\ncrush157/hello-smith       latest              a430ff69520c        2 hours ago         2.3MB\nruby                       2.4.2-alpine3.6     8647c16e6bb0        8 days ago          72MB\ncrush157/smith-httpd       latest              9d1ba46c4fb0        11 days ago         4.76MB\ncrush157/squash-dogsbody   latest              a8e0ddf918b5        12 days ago         934MB\ncrush157/dogsbody          latest              18e67fa6c47e        12 days ago         934MB\njruby                      latest              300c281a1aca        13 days ago         594MB\nruby                       latest              c7715c1eb8fe        2 weeks ago         687MB\nhttpd                      latest              74ad7f48867f        2 weeks ago         177MB\ndebian                     latest              6d83de432e98        2 weeks ago         100MB\nalpine                     latest              053cde6e8953        2 weeks ago         3.97MB\nmysql/mysql-server         latest              a3ee341faefb        5 weeks ago         246MB\n```\nAnd we see that we've gone from 934MB down to 83.4MB!\n\nWith a little extra work, you can even knock of another 2MB!  The smith.yaml for that is:\n```\ntype: oci\npackage: dogsbody-image.tgz\npaths:\n- /app/\n- /usr/local/bin/ruby\n- /usr/local/bin/rake\n- /usr/local/lib/libruby.so\n- /usr/local/lib/ruby\n- /usr/local/bundle\ncmd:\n- ruby\n- app.rb\n- '-e production'\n```\n15.  Now you've worked through the example, why don't you try to shrink one of your own images?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrush-157%2Fsmith-lab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrush-157%2Fsmith-lab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrush-157%2Fsmith-lab/lists"}